static void *Run (void *data) { services_discovery_t *sd = data; services_discovery_sys_t *p_sys = sd->p_sys; xcb_connection_t *conn = p_sys->conn; int fd = xcb_get_file_descriptor (conn); if (fd == -1) return NULL; while (!xcb_connection_has_error (conn)) { xcb_generic_event_t *ev; struct pollfd ufd = { .fd = fd, .events = POLLIN, }; poll (&ufd, 1, -1); int canc = vlc_savecancel (); while ((ev = xcb_poll_for_event (conn)) != NULL) { if ((ev->response_type & 0x7F) == XCB_PROPERTY_NOTIFY) { const xcb_property_notify_event_t *pn = (xcb_property_notify_event_t *)ev; if (pn->atom == p_sys->net_client_list) UpdateApps (sd); } free (ev); } vlc_restorecancel (canc); } return NULL; }
/** Background thread for X11 events handling */ static void *Thread (void *data) { vout_window_t *wnd = data; vout_window_sys_t *p_sys = wnd->sys; xcb_connection_t *conn = p_sys->conn; int fd = xcb_get_file_descriptor (conn); if (fd == -1) return NULL; for (;;) { xcb_generic_event_t *ev; struct pollfd ufd = { .fd = fd, .events = POLLIN, }; poll (&ufd, 1, -1); int canc = vlc_savecancel (); while ((ev = xcb_poll_for_event (conn)) != NULL) { if (ProcessKeyEvent (p_sys->keys, ev) == 0) continue; msg_Dbg (wnd, "unhandled event: %"PRIu8, ev->response_type); free (ev); } vlc_restorecancel (canc); if (xcb_connection_has_error (conn)) { msg_Err (wnd, "X server failure"); break; } } return NULL; }
static VkResult x11_acquire_next_image_poll_x11(struct x11_swapchain *chain, uint32_t *image_index, uint64_t timeout) { xcb_generic_event_t *event; struct pollfd pfds; uint64_t atimeout; while (1) { for (uint32_t i = 0; i < chain->image_count; i++) { if (!chain->images[i].busy) { /* We found a non-busy image */ xshmfence_await(chain->images[i].shm_fence); *image_index = i; chain->images[i].busy = true; return VK_SUCCESS; } } xcb_flush(chain->conn); if (timeout == UINT64_MAX) { event = xcb_wait_for_special_event(chain->conn, chain->special_event); if (!event) return VK_ERROR_OUT_OF_DATE_KHR; } else { event = xcb_poll_for_special_event(chain->conn, chain->special_event); if (!event) { int ret; if (timeout == 0) return VK_NOT_READY; atimeout = wsi_get_absolute_timeout(timeout); pfds.fd = xcb_get_file_descriptor(chain->conn); pfds.events = POLLIN; ret = poll(&pfds, 1, timeout / 1000 / 1000); if (ret == 0) return VK_TIMEOUT; if (ret == -1) return VK_ERROR_OUT_OF_DATE_KHR; /* If a non-special event happens, the fd will still * poll. So recalculate the timeout now just in case. */ uint64_t current_time = wsi_get_current_time(); if (atimeout > current_time) timeout = atimeout - current_time; else timeout = 0; continue; } } VkResult result = x11_handle_dri3_present_event(chain, (void *)event); free(event); if (result != VK_SUCCESS) return result; } }
static void *Thread( void *p_data ) { intf_thread_t *p_intf = p_data; intf_sys_t *p_sys = p_intf->p_sys; xcb_connection_t *p_connection = p_sys->p_connection; int canc = vlc_savecancel(); /* */ xcb_flush( p_connection ); /* */ int fd = xcb_get_file_descriptor( p_connection ); for( ;; ) { /* Wait for x11 event */ vlc_restorecancel( canc ); struct pollfd fds = { .fd = fd, .events = POLLIN, }; if( poll( &fds, 1, -1 ) < 0 ) { if( errno != EINTR ) break; canc = vlc_savecancel(); continue; } canc = vlc_savecancel(); xcb_generic_event_t *p_event; while( ( p_event = xcb_poll_for_event( p_connection ) ) ) { if( ( p_event->response_type & 0x7f ) != XCB_KEY_PRESS ) { free( p_event ); continue; } xcb_key_press_event_t *e = (xcb_key_press_event_t *)p_event; for( int i = 0; i < p_sys->i_map; i++ ) { hotkey_mapping_t *p_map = &p_sys->p_map[i]; for( int j = 0; p_map->p_keys[j] != XCB_NO_SYMBOL; j++ ) if( p_map->p_keys[j] == e->detail && p_map->i_modifier == e->state ) { var_SetInteger( p_intf->p_libvlc, "global-key-pressed", p_map->i_vlc ); goto done; } } done: free( p_event ); } } return NULL; }
void run_config(void) { if (fork() == 0) { if (dpy != NULL) close(xcb_get_file_descriptor(dpy)); setsid(); execl(config_path, config_path, NULL); err("Couldn't execute the configuration file.\n"); } }
QXcbConnection::QXcbConnection(const char *displayName) : m_displayName(displayName ? QByteArray(displayName) : qgetenv("DISPLAY")) #ifdef XCB_USE_DRI2 , m_dri2_major(0) , m_dri2_minor(0) , m_dri2_support_probed(false) , m_has_support_for_dri2(false) #endif { int primaryScreen = 0; #ifdef XCB_USE_XLIB Display *dpy = XOpenDisplay(m_displayName.constData()); primaryScreen = DefaultScreen(dpy); m_connection = XGetXCBConnection(dpy); XSetEventQueueOwner(dpy, XCBOwnsEventQueue); m_xlib_display = dpy; #ifdef XCB_USE_EGL EGLDisplay eglDisplay = eglGetDisplay(dpy); m_egl_display = eglDisplay; EGLint major, minor; eglBindAPI(EGL_OPENGL_ES_API); m_has_egl = eglInitialize(eglDisplay,&major,&minor); #endif //XCB_USE_EGL #else m_connection = xcb_connect(m_displayName.constData(), &primaryScreen); #endif //XCB_USE_XLIB m_setup = xcb_get_setup(xcb_connection()); initializeAllAtoms(); xcb_screen_iterator_t it = xcb_setup_roots_iterator(m_setup); int screenNumber = 0; while (it.rem) { m_screens << new QXcbScreen(this, it.data, screenNumber++); xcb_screen_next(&it); } m_keyboard = new QXcbKeyboard(this); #ifdef XCB_USE_DRI2 initializeDri2(); #endif QSocketNotifier *notifier = new QSocketNotifier(xcb_get_file_descriptor(xcb_connection()), QSocketNotifier::Read, this); connect(notifier, SIGNAL(activated(int)), this, SLOT(processXcbEvents())); QAbstractEventDispatcher *dispatcher = QAbstractEventDispatcher::instance(qApp->thread()); connect(dispatcher, SIGNAL(aboutToBlock()), this, SLOT(processXcbEvents())); sync(); }
void spawn(const struct arg_t *arg) { pid_t pid; pid = fork(); if (pid == 0) { /* child process */ close(xcb_get_file_descriptor(nil_.con)); setsid(); execvp(((char **)arg->v)[0], (char **)arg->v); NIL_ERR("execvp %s", ((char **)arg->v)[0]); exit(1); } else if (pid < 0) { NIL_ERR("fork %d", pid); } }
void X11WindowedBackend::startEventReading() { QSocketNotifier *notifier = new QSocketNotifier(xcb_get_file_descriptor(m_connection), QSocketNotifier::Read, this); auto processXcbEvents = [this] { while (auto event = xcb_poll_for_event(m_connection)) { handleEvent(event); free(event); } xcb_flush(m_connection); }; connect(notifier, &QSocketNotifier::activated, this, processXcbEvents); connect(QCoreApplication::eventDispatcher(), &QAbstractEventDispatcher::aboutToBlock, this, processXcbEvents); connect(QCoreApplication::eventDispatcher(), &QAbstractEventDispatcher::awake, this, processXcbEvents); }
XRecordKeyboardMonitor::XRecordKeyboardMonitor(Display *display) : m_connection(xcb_connect(XDisplayString(display), 0)), m_modifiersPressed(0), m_keysPressed(0) { if (!m_connection) { return; } xcb_get_modifier_mapping_cookie_t modmapCookie = xcb_get_modifier_mapping(m_connection); m_context = xcb_generate_id(m_connection); xcb_record_range_t range; memset(&range, 0, sizeof(range)); range.device_events.first = XCB_KEY_PRESS; range.device_events.last = XCB_KEY_RELEASE; xcb_record_client_spec_t cs = XCB_RECORD_CS_ALL_CLIENTS; xcb_record_create_context(m_connection, m_context, 0, 1, 1, &cs, &range); xcb_flush(m_connection); QScopedPointer<xcb_get_modifier_mapping_reply_t, QScopedPointerPodDeleter> modmap(xcb_get_modifier_mapping_reply(m_connection, modmapCookie, 0)); if (!modmap) { return; } int nModifiers = xcb_get_modifier_mapping_keycodes_length(modmap.data()); xcb_keycode_t *modifiers = xcb_get_modifier_mapping_keycodes(modmap.data()); m_modifier.fill(false, std::numeric_limits<xcb_keycode_t>::max() + 1); for (xcb_keycode_t *i = modifiers; i < modifiers + nModifiers; i++) { m_modifier[*i] = true; } m_ignore.fill(false, std::numeric_limits<xcb_keycode_t>::max() + 1); for (xcb_keycode_t *i = modifiers; i < modifiers + modmap->keycodes_per_modifier; i++) { m_ignore[*i] = true; } m_pressed.fill(false, std::numeric_limits<xcb_keycode_t>::max() + 1); m_cookie = xcb_record_enable_context(m_connection, m_context); xcb_flush(m_connection); m_notifier = new QSocketNotifier(xcb_get_file_descriptor(m_connection), QSocketNotifier::Read, this); connect(m_notifier, SIGNAL(activated(int)), SLOT(processNextReply())); m_notifier->setEnabled(true); }
void spawn(char *cmd[], bool sync) { if (fork() == 0) { if (dpy != NULL) close(xcb_get_file_descriptor(dpy)); if (sync) { execute(cmd); } else { if (fork() == 0) { execute(cmd); } exit(EXIT_SUCCESS); } } wait(NULL); }
void spawn(char *cmd[]) { if (fork() == 0) { if (dpy != NULL) close(xcb_get_file_descriptor(dpy)); if (fork() == 0) { setsid(); if (redir_fd != -1) { dup2(redir_fd, STDOUT_FILENO); dup2(redir_fd, STDERR_FILENO); } execvp(cmd[0], cmd); err("Spawning failed.\n"); } exit(EXIT_SUCCESS); } wait(NULL); }
xconn_t xconn_open(const char *display) { XConnSource *s; xcb_connection_t *dpy; xconn_t c; int fd; dpy=xcb_connect(display,0); /* is error in setup stage, there is memory leak at xcb */ if(!dpy || xcb_connection_has_error(dpy)) return NULL; c=malloc(sizeof(*c)); c->c=dpy; fd=xcb_get_file_descriptor(dpy); s=(XConnSource*)g_source_new(&xconn_funcs,sizeof(XConnSource)); g_source_set_callback((GSource*)s,(GSourceFunc)xconn_func,c,NULL); s->poll.fd=fd; s->poll.events=G_IO_IN; g_source_add_poll((GSource*)s,&s->poll); c->id=g_source_attach((GSource*)s,NULL); return c; }
void run_autostart(void) { char path[MAXLEN]; char *config_home = getenv(CONFIG_HOME_ENV); if (config_home != NULL) snprintf(path, sizeof(path), "%s/%s/%s", config_home, WM_NAME, AUTOSTART_FILE); else snprintf(path, sizeof(path), "%s/%s/%s/%s", getenv("HOME"), ".config", WM_NAME, AUTOSTART_FILE); if (fork() == 0) { if (dpy != NULL) close(xcb_get_file_descriptor(dpy)); if (fork() == 0) { setsid(); execl(path, path, NULL); err("Couldn't spawn the autostart file.\n"); } exit(EXIT_SUCCESS); } wait(NULL); }
/** 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; }
int main(int argc, char *argv[]) { char opt; char *fifo_path = NULL; char *socket_path = NULL; status_fifo = NULL; config_path = NULL; mapping_count = 0; timeout = TIMEOUT; grabbed = false; sock_address.sun_family = AF_UNIX; sock_address.sun_path[0] = 0; snprintf(motion_msg_tpl, sizeof(motion_msg_tpl), "%s", MOTION_MSG_TPL); unsigned int max_freq = 0; motion_interval = 0; last_motion_time = 0; redir_fd = -1; while ((opt = getopt(argc, argv, "vhm:t:c:r:s:f:o:g:")) != (char)-1) { switch (opt) { case 'v': printf("%s\n", VERSION); exit(EXIT_SUCCESS); break; case 'h': printf("sxhkd [-h|-v|-m COUNT|-t TIMEOUT|-c CONFIG_FILE|-r REDIR_FILE|-s STATUS_FIFO|-o MOTION_SOCKET|-g MOTION_MSG_TPL] [EXTRA_CONFIG ...]\n"); exit(EXIT_SUCCESS); break; case 'm': if (sscanf(optarg, "%i", &mapping_count) != 1) warn("Can't parse mapping count.\n"); break; case 't': timeout = atoi(optarg); break; case 'c': config_path = optarg; break; case 'r': redir_fd = open(optarg, O_WRONLY | O_CREAT, S_IRUSR | S_IWUSR | S_IRGRP | S_IROTH); if (redir_fd == -1) warn("Failed to open the command redirection file.\n"); break; case 's': fifo_path = optarg; break; case 'o': socket_path = optarg; break; case 'g': snprintf(motion_msg_tpl, sizeof(motion_msg_tpl), "%s", optarg); break; case 'f': if (sscanf(optarg, "%u", &max_freq) != 1) warn("Can't parse maximum pointer frequency.\n"); break; } } num_extra_confs = argc - optind; extra_confs = argv + optind; if (config_path == NULL) { char *config_home = getenv(CONFIG_HOME_ENV); if (config_home != NULL) snprintf(config_file, sizeof(config_file), "%s/%s", config_home, CONFIG_PATH); else snprintf(config_file, sizeof(config_file), "%s/%s/%s", getenv("HOME"), ".config", CONFIG_PATH); } else { snprintf(config_file, sizeof(config_file), "%s", config_path); } if (socket_path == NULL) { socket_path = getenv(SOCKET_ENV); } if (socket_path == NULL) { char *host = NULL; int dn = 0, sn = 0; if (xcb_parse_display(NULL, &host, &dn, &sn) != 0) { snprintf(sock_address.sun_path, sizeof(sock_address.sun_path), SOCKET_PATH_TPL, host, dn, sn); } else { warn("Failed to set motion socket address."); } free(host); } else { snprintf(sock_address.sun_path, sizeof(sock_address.sun_path), "%s", socket_path); } if (fifo_path != NULL) { int fifo_fd = open(fifo_path, O_RDWR | O_NONBLOCK); if (fifo_fd != -1) status_fifo = fdopen(fifo_fd, "w"); else warn("Couldn't open status fifo.\n"); } if (max_freq != 0) motion_interval = 1000.0 / max_freq; signal(SIGINT, hold); signal(SIGHUP, hold); signal(SIGTERM, hold); signal(SIGUSR1, hold); signal(SIGUSR2, hold); signal(SIGALRM, hold); setup(); get_standard_keysyms(); get_lock_fields(); escape_chord = make_chord(ESCAPE_KEYSYM, XCB_NONE, 0, XCB_KEY_PRESS, false, false); load_config(config_file); for (int i = 0; i < num_extra_confs; i++) load_config(extra_confs[i]); grab(); xcb_generic_event_t *evt; int fd = xcb_get_file_descriptor(dpy); fd_set descriptors; reload = toggle_grab = bell = chained = locked = false; running = true; xcb_flush(dpy); while (running) { FD_ZERO(&descriptors); FD_SET(fd, &descriptors); if (select(fd + 1, &descriptors, NULL, NULL, NULL) > 0) { while ((evt = xcb_poll_for_event(dpy)) != NULL) { uint8_t event_type = XCB_EVENT_RESPONSE_TYPE(evt); switch (event_type) { case XCB_KEY_PRESS: case XCB_KEY_RELEASE: case XCB_BUTTON_PRESS: case XCB_BUTTON_RELEASE: key_button_event(evt, event_type); break; case XCB_MOTION_NOTIFY: motion_notify(evt); break; case XCB_MAPPING_NOTIFY: mapping_notify(evt); break; default: PRINTF("received event %u\n", event_type); break; } free(evt); } } if (reload) { signal(SIGUSR1, hold); reload_cmd(); reload = false; } if (toggle_grab) { signal(SIGUSR2, hold); toggle_grab_cmd(); toggle_grab = false; } if (bell) { signal(SIGALRM, hold); abort_chain(); if (status_fifo != NULL) put_status(TIMEOUT_PREFIX, "Timeout reached"); bell = false; } if (xcb_connection_has_error(dpy)) { warn("The server closed the connection.\n"); running = false; } } if (redir_fd != -1) close(redir_fd); if (status_fifo != NULL) fclose(status_fifo); ungrab(); cleanup(); destroy_chord(escape_chord); xcb_key_symbols_free(symbols); xcb_disconnect(dpy); return EXIT_SUCCESS; }
int main(int argc, char *argv[]) { setlocale(LC_TIME, "ru_RU.UTF-8"); char *username; char *image_path = NULL; int ret; struct pam_conv conv = {conv_callback, NULL}; int curs_choice = CURS_NONE; int o; int optind = 0; struct option longopts[] = { {"version", no_argument, NULL, 'v'}, {"nofork", no_argument, NULL, 'n'}, {"beep", no_argument, NULL, 'b'}, {"dpms", no_argument, NULL, 'd'}, {"color", required_argument, NULL, 'c'}, {"pointer", required_argument, NULL , 'p'}, {"debug", no_argument, NULL, 0}, {"help", no_argument, NULL, 'h'}, {"no-unlock-indicator", no_argument, NULL, 'u'}, {"image", required_argument, NULL, 'i'}, {"tiling", no_argument, NULL, 't'}, {"auth-fail-command", required_argument, NULL, 'f'}, {"auth-done-command", required_argument, NULL, 'o'}, {NULL, no_argument, NULL, 0} }; if ((username = getenv("USER")) == NULL) errx(1, "USER environment variable not set, please set it.\n"); while ((o = getopt_long(argc, argv, "hvnbdc:p:ui:f:o:t", longopts, &optind)) != -1) { switch (o) { case 'v': errx(EXIT_SUCCESS, "version " VERSION " © 2010-2012 Michael Stapelberg"); case 'n': dont_fork = true; break; case 'b': beep = true; break; case 'd': dpms = true; break; case 'c': { char *arg = optarg; /* Skip # if present */ if (arg[0] == '#') arg++; if (strlen(arg) != 6 || sscanf(arg, "%06[0-9a-fA-F]", color) != 1) errx(1, "color is invalid, it must be given in 3-byte hexadecimal format: rrggbb\n"); break; } case 'u': unlock_indicator = false; break; case 'i': image_path = strdup(optarg); break; case 't': tile = true; break; case 'p': if (!strcmp(optarg, "win")) { curs_choice = CURS_WIN; } else if (!strcmp(optarg, "default")) { curs_choice = CURS_DEFAULT; } else { errx(1, "i3lock: Invalid pointer type given. Expected one of \"win\" or \"default\".\n"); } break; case 'f': shell_auth_fail_command = strdup(optarg); break; case 'o': shell_auth_done_command = strdup(optarg); break; case 'h': show_time = false; break; case 0: if (strcmp(longopts[optind].name, "debug") == 0) debug_mode = true; break; default: errx(1, "Syntax: i3lock [-v] [-n] [-b] [-d] [-c color] [-u] [-p win|default] [-h]" " [-i image.png] [-t] [-f command] [-o command]" ); } } /* We need (relatively) random numbers for highlighting a random part of * the unlock indicator upon keypresses. */ srand(time(NULL)); /* Initialize PAM */ ret = pam_start("i3lock", username, &conv, &pam_handle); if (ret != PAM_SUCCESS) errx(EXIT_FAILURE, "PAM: %s", pam_strerror(pam_handle, ret)); /* Using mlock() as non-super-user seems only possible in Linux. Users of other * operating systems should use encrypted swap/no swap (or remove the ifdef and * run i3lock as super-user). */ #if defined(__linux__) /* Lock the area where we store the password in memory, we don’t want it to * be swapped to disk. Since Linux 2.6.9, this does not require any * privileges, just enough bytes in the RLIMIT_MEMLOCK limit. */ if (mlock(password, sizeof(password)) != 0) err(EXIT_FAILURE, "Could not lock page in memory, check RLIMIT_MEMLOCK"); #endif /* Initialize connection to X11 */ if ((display = XOpenDisplay(NULL)) == NULL) errx(EXIT_FAILURE, "Could not connect to X11, maybe you need to set DISPLAY?"); XSetEventQueueOwner(display, XCBOwnsEventQueue); conn = XGetXCBConnection(display); /* Double checking that connection is good and operatable with xcb */ if (xcb_connection_has_error(conn)) errx(EXIT_FAILURE, "Could not connect to X11, maybe you need to set DISPLAY?"); /* When we cannot initially load the keymap, we better exit */ if (!load_keymap()) errx(EXIT_FAILURE, "Could not load keymap"); xinerama_init(); xinerama_query_screens(); /* if DPMS is enabled, check if the X server really supports it */ if (dpms) { xcb_dpms_capable_cookie_t dpmsc = xcb_dpms_capable(conn); xcb_dpms_capable_reply_t *dpmsr; if ((dpmsr = xcb_dpms_capable_reply(conn, dpmsc, NULL))) { if (!dpmsr->capable) { if (debug_mode) fprintf(stderr, "Disabling DPMS, X server not DPMS capable\n"); dpms = false; } free(dpmsr); } } screen = xcb_setup_roots_iterator(xcb_get_setup(conn)).data; last_resolution[0] = screen->width_in_pixels; last_resolution[1] = screen->height_in_pixels; xcb_change_window_attributes(conn, screen->root, XCB_CW_EVENT_MASK, (uint32_t[]){ XCB_EVENT_MASK_STRUCTURE_NOTIFY }); if (image_path) { /* Create a pixmap to render on, fill it with the background color */ img = cairo_image_surface_create_from_png(image_path); /* In case loading failed, we just pretend no -i was specified. */ if (cairo_surface_status(img) != CAIRO_STATUS_SUCCESS) { fprintf(stderr, "Could not load image \"%s\": cairo surface status %d\n", image_path, cairo_surface_status(img)); img = NULL; } } /* Pixmap on which the image is rendered to (if any) */ xcb_pixmap_t bg_pixmap = draw_image(last_resolution); /* open the fullscreen window, already with the correct pixmap in place */ win = open_fullscreen_window(conn, screen, color, bg_pixmap); xcb_free_pixmap(conn, bg_pixmap); cursor = create_cursor(conn, screen, win, curs_choice); grab_pointer_and_keyboard(conn, screen, cursor); if (dpms) dpms_turn_off_screen(conn); /* Initialize the libev event loop. */ main_loop = EV_DEFAULT; if (main_loop == NULL) errx(EXIT_FAILURE, "Could not initialize libev. Bad LIBEV_FLAGS?\n"); struct ev_io *xcb_watcher = calloc(sizeof(struct ev_io), 1); struct ev_check *xcb_check = calloc(sizeof(struct ev_check), 1); struct ev_prepare *xcb_prepare = calloc(sizeof(struct ev_prepare), 1); ev_io_init(xcb_watcher, xcb_got_event, xcb_get_file_descriptor(conn), EV_READ); ev_io_start(main_loop, xcb_watcher); ev_check_init(xcb_check, xcb_check_cb); ev_check_start(main_loop, xcb_check); ev_prepare_init(xcb_prepare, xcb_prepare_cb); ev_prepare_start(main_loop, xcb_prepare); /* Invoke the event callback once to catch all the events which were * received up until now. ev will only pick up new events (when the X11 * file descriptor becomes readable). */ ev_invoke(main_loop, xcb_check, 0); if(show_time) start_time_redraw_tick(); ev_loop(main_loop, 0); }
/** Background thread for X11 events handling */ static void *Thread (void *data) { vout_window_t *wnd = data; vout_window_sys_t *p_sys = wnd->sys; xcb_connection_t *conn = p_sys->conn; int fd = xcb_get_file_descriptor (conn); if (fd == -1) return NULL; for (;;) { xcb_generic_event_t *ev; struct pollfd ufd = { .fd = fd, .events = POLLIN, }; poll (&ufd, 1, -1); int canc = vlc_savecancel (); while ((ev = xcb_poll_for_event (conn)) != NULL) { if (ProcessKeyEvent (p_sys->keys, ev) == 0) continue; #ifdef MATCHBOX_HACK if (p_sys->mb_current_app_window && (ev->response_type & 0x7f) == XCB_PROPERTY_NOTIFY) { const xcb_property_notify_event_t *pne = (xcb_property_notify_event_t *)ev; if (pne->atom == p_sys->mb_current_app_window && pne->state == XCB_PROPERTY_NEW_VALUE) { xcb_get_property_reply_t *r = xcb_get_property_reply (conn, xcb_get_property (conn, 0, pne->window, pne->atom, XA_WINDOW, 0, 4), NULL); if (r != NULL && !memcmp (xcb_get_property_value (r), &wnd->handle.xid, 4)) { msg_Dbg (wnd, "asking Matchbox for input focus"); xcb_set_input_focus (conn, XCB_INPUT_FOCUS_POINTER_ROOT, wnd->handle.xid, pne->time); xcb_flush (conn); } free (r); } } else #endif msg_Dbg (wnd, "unhandled event: %"PRIu8, ev->response_type); free (ev); } vlc_restorecancel (canc); if (xcb_connection_has_error (conn)) { msg_Err (wnd, "X server failure"); break; } } return NULL; }
X11Backend::X11Backend(Compositor& comp, Seat& seat) : Backend(), compositor_(&comp), seat_(&seat) { //setup x connection xDisplay_ = XOpenDisplay(nullptr); if(!xDisplay_) { throw std::runtime_error("cant connect to x11 server"); return; } xConnection_ = XGetXCBConnection(xDisplay_); if(!xConnection_) { throw std::runtime_error("cant get xcb connection"); return; } XSetEventQueueOwner(xDisplay_, XCBOwnsEventQueue); if(xcb_connection_has_error(xConnection_)) { throw std::runtime_error("xcb connection error"); return; } xScreen_ = xcb_setup_roots_iterator(xcb_get_setup(xConnection_)).data; //atoms struct atomProp { xcb_atom_t& ret; std::string str; }; atomProp vec[] = { {atoms::protocols, "WM_PROTOCOLS"}, {atoms::deleteWindow, "WM_DELETE_WINDOW"} }; xcb_intern_atom_reply_t* reply; for(auto& p : vec) { auto atom = xcb_intern_atom(xConnection_, 0, p.str.size(), p.str.c_str()); reply = xcb_intern_atom_reply(xConnection_, atom, nullptr); p.ret = (reply ? reply->atom : 0); } //xkb xkbSetup(); //event source inputEventSource_ = wl_event_loop_add_fd(&comp.wlEventLoop(), xcb_get_file_descriptor(xConnection_), WL_EVENT_READABLE, eventCallback, this); if(!inputEventSource_) throw std::runtime_error("could not create wayland event source"); //what does this? really needed? wl_event_source_check(inputEventSource_); //eglContext eglContext_ = std::make_unique<WaylandEglContext>(xDisplay_); if(!eglContext_) throw std::runtime_error("x11Backend::x11Backend: failed to create EglContext"); eglContext_->bindWlDisplay(compositor_->wlDisplay()); xcb_flush(xConnection_); }
void* widget_main (struct widget *widget) { unsigned short i; int xcb_fd; int screen_nbr = 0; xcb_connection_t *conn = xcb_connect(NULL, NULL); xcb_ewmh_connection_t *ewmh = malloc(sizeof(xcb_ewmh_connection_t)); struct epoll_event xcb_event; widget_epoll_init(widget); if (xcb_connection_has_error(conn)) { LOG_ERR("could not connect to display %s", getenv("DISPLAY")); goto cleanup; } xcb_intern_atom_cookie_t *ewmh_cookie = xcb_ewmh_init_atoms(conn, ewmh); xcb_ewmh_init_atoms_replies(ewmh, ewmh_cookie, NULL); uint32_t values[] = { XCB_EVENT_MASK_PROPERTY_CHANGE }; xcb_generic_event_t *evt; xcb_generic_error_t *err = xcb_request_check(ewmh->connection, xcb_change_window_attributes_checked(ewmh->connection, ewmh->screens[screen_nbr]->root, XCB_CW_EVENT_MASK, values)); if (err != NULL) { LOG_ERR("could not request EWMH property change notifications"); goto cleanup; } xcb_fd = xcb_get_file_descriptor(ewmh->connection); xcb_event.data.fd = xcb_fd; xcb_event.events = EPOLLIN | EPOLLET; if (epoll_ctl(efd, EPOLL_CTL_ADD, xcb_fd, &xcb_event) == -1) { LOG_ERR("failed to add fd to epoll instance: %s", strerror(errno)); return 0; } widget_update(widget, ewmh, screen_nbr); while (true) { while ((nfds = epoll_wait(efd, events, MAX_EVENTS, -1)) > 0) { for (i = 0; i < nfds; i++) { if (events[i].data.fd == widget->bar->efd) { goto cleanup; } } while ((evt = xcb_poll_for_event(ewmh->connection)) != NULL) { xcb_property_notify_event_t *pne; switch (XCB_EVENT_RESPONSE_TYPE(evt)) { case XCB_PROPERTY_NOTIFY: pne = (xcb_property_notify_event_t*)evt; if (pne->atom == ewmh->_NET_DESKTOP_NAMES) { widget_update(widget, ewmh, screen_nbr); } else if (pne->atom == ewmh->_NET_NUMBER_OF_DESKTOPS) { widget_update(widget, ewmh, screen_nbr); } else if (pne->atom == ewmh->_NET_CURRENT_DESKTOP) { widget_update(widget, ewmh, screen_nbr); } default: break; } free(evt); } } } cleanup: if (ewmh != NULL) { xcb_ewmh_connection_wipe(ewmh); } if (conn != NULL) { xcb_disconnect(conn); } widget_epoll_cleanup(widget); widget_clean_exit(widget); }
virtual int get_file_descriptor(void) const { return xcb_get_file_descriptor(m_c.get()); }
/** 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, opt; ssize_t cmdlen = 1; xdgHandle xdg; bool no_argb = false; xcb_generic_event_t *event; xcb_query_tree_cookie_t tree_c; static struct option long_options[] = { { "help", 0, NULL, 'h' }, { "version", 0, NULL, 'v' }, { "config", 1, NULL, 'c' }, { "check", 0, NULL, 'k' }, { "no-argb", 0, NULL, 'a' }, { 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; awesome_argv = p_new(char, cmdlen); a_strcpy(awesome_argv, cmdlen, argv[0]); for(i = 1; i < argc; i++) { a_strcat(awesome_argv, cmdlen, " "); a_strcat(awesome_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:a", 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; case 'a': no_argb = true; break; } globalconf.loop = ev_default_loop(EVFLAG_NOSIGFD); /* 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); /* X stuff */ globalconf.connection = xcb_connect(NULL, &globalconf.default_screen); if(xcb_connection_has_error(globalconf.connection)) fatal("cannot open display"); globalconf.screen = xcb_aux_get_screen(globalconf.connection, globalconf.default_screen); /* FIXME The following two assignments were swapped on purpose */ if(!no_argb) globalconf.visual = a_default_visual(globalconf.screen); if(!globalconf.visual) globalconf.visual = a_argb_visual(globalconf.screen); globalconf.default_depth = a_visual_depth(globalconf.screen, globalconf.visual->visual_id); globalconf.default_cmap = globalconf.screen->default_colormap; if(globalconf.default_depth != globalconf.screen->root_depth) { // We need our own color map if we aren't using the default depth globalconf.default_cmap = xcb_generate_id(globalconf.connection); xcb_create_colormap(globalconf.connection, XCB_COLORMAP_ALLOC_NONE, globalconf.default_cmap, globalconf.screen->root, globalconf.visual->visual_id); } /* 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_xinerama_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); } { 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, globalconf.screen->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(); xutil_lock_mask_get(globalconf.connection, xmapping_cookie, globalconf.keysyms, &globalconf.numlockmask, &globalconf.shiftlockmask, &globalconf.capslockmask, &globalconf.modeswitchmask); /* do this only for real screen */ ewmh_init(); systray_init(); /* init spawn (sn) */ spawn_init(); /* The default GC is just a newly created associated with a window with * depth globalconf.default_depth */ xcb_window_t tmp_win = xcb_generate_id(globalconf.connection); globalconf.gc = xcb_generate_id(globalconf.connection); xcb_create_window(globalconf.connection, globalconf.default_depth, tmp_win, globalconf.screen->root, -1, -1, 1, 1, 0, XCB_COPY_FROM_PARENT, globalconf.visual->visual_id, XCB_CW_BACK_PIXEL | XCB_CW_BORDER_PIXEL | XCB_CW_COLORMAP, (const uint32_t []) { globalconf.screen->black_pixel, globalconf.screen->black_pixel, globalconf.default_cmap }); xcb_create_gc(globalconf.connection, globalconf.gc, tmp_win, XCB_GC_FOREGROUND | XCB_GC_BACKGROUND, (const uint32_t[]) { globalconf.screen->black_pixel, globalconf.screen->white_pixel }); xcb_destroy_window(globalconf.connection, tmp_win); /* Get the window tree associated to this screen */ tree_c = xcb_query_tree_unchecked(globalconf.connection, globalconf.screen->root); xcb_change_window_attributes(globalconf.connection, globalconf.screen->root, XCB_CW_EVENT_MASK, ROOT_WINDOW_EVENT_MASK); /* 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"); p_delete(&confpath); xdgWipeHandle(&xdg); /* scan existing windows */ 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; }
int main(int argc, char *argv[]) { bool snoop = false; char *format = NULL; char opt; while ((opt = getopt(argc, argv, "hvsf:")) != -1) { switch (opt) { case 'h': printf("xtitle [-h|-v|-s|-f FORMAT] [WID ...]\n"); return EXIT_SUCCESS; break; case 'v': printf("%s\n", VERSION); return EXIT_SUCCESS; break; case 's': snoop = true; break; case 'f': format = optarg; break; } } int num = argc - optind; char **args = argv + optind; setup(); char title[MAXLEN] = {0}; if (num > 0) { char *end; for (int i = 0; i < num; i++) { errno = 0; long int wid = strtol(args[i], &end, 0); if (errno != 0 || *end != '\0') warn("Invalid window ID: '%s'.\n", args[i]); else output_title(wid, format, title, sizeof(title)); } } else { xcb_window_t win = XCB_NONE; if (get_active_window(&win)) output_title(win, format, title, sizeof(title)); if (snoop) { signal(SIGINT, hold); signal(SIGHUP, hold); signal(SIGTERM, hold); watch(root, true); watch(win, true); xcb_window_t last_win = XCB_NONE; fd_set descriptors; int fd = xcb_get_file_descriptor(dpy); running = true; xcb_flush(dpy); while (running) { FD_ZERO(&descriptors); FD_SET(fd, &descriptors); if (select(fd + 1, &descriptors, NULL, NULL, NULL) > 0) { xcb_generic_event_t *evt; while ((evt = xcb_poll_for_event(dpy)) != NULL) { if (title_changed(evt, &win, &last_win)) output_title(win, format, title, sizeof(title)); free(evt); } } if (xcb_connection_has_error(dpy)) { warn("The server closed the connection.\n"); running = false; } } } } xcb_ewmh_connection_wipe(ewmh); free(ewmh); xcb_disconnect(dpy); return EXIT_SUCCESS; }
int main(int argc, char *argv[]) { struct passwd *pw; char *username; char *image_path = NULL; int ret; struct pam_conv conv = {conv_callback, NULL}; int curs_choice = CURS_NONE; int o; int optind = 0; struct option longopts[] = { {"version", no_argument, NULL, 'v'}, {"nofork", no_argument, NULL, 'n'}, {"beep", no_argument, NULL, 'b'}, {"dpms", no_argument, NULL, 'd'}, {"color", required_argument, NULL, 'c'}, {"pointer", required_argument, NULL, 'p'}, {"debug", no_argument, NULL, 0}, {"help", no_argument, NULL, 'h'}, {"no-unlock-indicator", no_argument, NULL, 'u'}, {"image", required_argument, NULL, 'i'}, {"tiling", no_argument, NULL, 't'}, {"ignore-empty-password", no_argument, NULL, 'e'}, {"inactivity-timeout", required_argument, NULL, 'I'}, {"show-failed-attempts", no_argument, NULL, 'f'}, {NULL, no_argument, NULL, 0} }; if ((pw = getpwuid(getuid())) == NULL) err(EXIT_FAILURE, "getpwuid() failed"); if ((username = pw->pw_name) == NULL) errx(EXIT_FAILURE, "pw->pw_name is NULL.\n"); char *optstring = "hvnbdc:p:ui:teI:f"; while ((o = getopt_long(argc, argv, optstring, longopts, &optind)) != -1) { switch (o) { case 'v': errx(EXIT_SUCCESS, "version " VERSION " © 2010 Michael Stapelberg"); case 'n': dont_fork = true; break; case 'b': beep = true; break; case 'd': fprintf(stderr, "DPMS support has been removed from i3lock. Please see the manpage i3lock(1).\n"); break; case 'I': { int time = 0; if (sscanf(optarg, "%d", &time) != 1 || time < 0) errx(EXIT_FAILURE, "invalid timeout, it must be a positive integer\n"); inactivity_timeout = time; break; } case 'c': { char *arg = optarg; /* Skip # if present */ if (arg[0] == '#') arg++; if (strlen(arg) != 6 || sscanf(arg, "%06[0-9a-fA-F]", color) != 1) errx(EXIT_FAILURE, "color is invalid, it must be given in 3-byte hexadecimal format: rrggbb\n"); break; } case 'u': unlock_indicator = false; break; case 'i': image_path = strdup(optarg); break; case 't': tile = true; break; case 'p': if (!strcmp(optarg, "win")) { curs_choice = CURS_WIN; } else if (!strcmp(optarg, "default")) { curs_choice = CURS_DEFAULT; } else { errx(EXIT_FAILURE, "i3lock: Invalid pointer type given. Expected one of \"win\" or \"default\".\n"); } break; case 'e': ignore_empty_password = true; break; case 0: if (strcmp(longopts[optind].name, "debug") == 0) debug_mode = true; break; case 'f': show_failed_attempts = true; break; default: errx(EXIT_FAILURE, "Syntax: i3lock [-v] [-n] [-b] [-d] [-c color] [-u] [-p win|default]" " [-i image.png] [-t] [-e] [-I timeout] [-f]"); } } /* We need (relatively) random numbers for highlighting a random part of * the unlock indicator upon keypresses. */ srand(time(NULL)); /* Initialize PAM */ ret = pam_start("i3lock", username, &conv, &pam_handle); if (ret != PAM_SUCCESS) errx(EXIT_FAILURE, "PAM: %s", pam_strerror(pam_handle, ret)); /* Using mlock() as non-super-user seems only possible in Linux. Users of other * operating systems should use encrypted swap/no swap (or remove the ifdef and * run i3lock as super-user). */ #if defined(__linux__) /* Lock the area where we store the password in memory, we don’t want it to * be swapped to disk. Since Linux 2.6.9, this does not require any * privileges, just enough bytes in the RLIMIT_MEMLOCK limit. */ if (mlock(password, sizeof(password)) != 0) err(EXIT_FAILURE, "Could not lock page in memory, check RLIMIT_MEMLOCK"); #endif /* Double checking that connection is good and operatable with xcb */ int screennr; if ((conn = xcb_connect(NULL, &screennr)) == NULL || xcb_connection_has_error(conn)) errx(EXIT_FAILURE, "Could not connect to X11, maybe you need to set DISPLAY?"); if (xkb_x11_setup_xkb_extension(conn, XKB_X11_MIN_MAJOR_XKB_VERSION, XKB_X11_MIN_MINOR_XKB_VERSION, 0, NULL, NULL, &xkb_base_event, &xkb_base_error) != 1) errx(EXIT_FAILURE, "Could not setup XKB extension."); static const xcb_xkb_map_part_t required_map_parts = (XCB_XKB_MAP_PART_KEY_TYPES | XCB_XKB_MAP_PART_KEY_SYMS | XCB_XKB_MAP_PART_MODIFIER_MAP | XCB_XKB_MAP_PART_EXPLICIT_COMPONENTS | XCB_XKB_MAP_PART_KEY_ACTIONS | XCB_XKB_MAP_PART_VIRTUAL_MODS | XCB_XKB_MAP_PART_VIRTUAL_MOD_MAP); static const xcb_xkb_event_type_t required_events = (XCB_XKB_EVENT_TYPE_NEW_KEYBOARD_NOTIFY | XCB_XKB_EVENT_TYPE_MAP_NOTIFY | XCB_XKB_EVENT_TYPE_STATE_NOTIFY); xcb_xkb_select_events( conn, xkb_x11_get_core_keyboard_device_id(conn), required_events, 0, required_events, required_map_parts, required_map_parts, 0); /* When we cannot initially load the keymap, we better exit */ if (!load_keymap()) errx(EXIT_FAILURE, "Could not load keymap"); const char *locale = getenv("LC_ALL"); if (!locale) locale = getenv("LC_CTYPE"); if (!locale) locale = getenv("LANG"); if (!locale) { if (debug_mode) fprintf(stderr, "Can't detect your locale, fallback to C\n"); locale = "C"; } load_compose_table(locale); xinerama_init(); xinerama_query_screens(); screen = xcb_setup_roots_iterator(xcb_get_setup(conn)).data; last_resolution[0] = screen->width_in_pixels; last_resolution[1] = screen->height_in_pixels; xcb_change_window_attributes(conn, screen->root, XCB_CW_EVENT_MASK, (uint32_t[]) { XCB_EVENT_MASK_STRUCTURE_NOTIFY }); if (image_path) { /* Create a pixmap to render on, fill it with the background color */ img = cairo_image_surface_create_from_png(image_path); /* In case loading failed, we just pretend no -i was specified. */ if (cairo_surface_status(img) != CAIRO_STATUS_SUCCESS) { fprintf(stderr, "Could not load image \"%s\": %s\n", image_path, cairo_status_to_string(cairo_surface_status(img))); img = NULL; } } /* Pixmap on which the image is rendered to (if any) */ xcb_pixmap_t bg_pixmap = draw_image(last_resolution); /* open the fullscreen window, already with the correct pixmap in place */ win = open_fullscreen_window(conn, screen, color, bg_pixmap); xcb_free_pixmap(conn, bg_pixmap); pid_t pid = fork(); /* The pid == -1 case is intentionally ignored here: * While the child process is useful for preventing other windows from * popping up while i3lock blocks, it is not critical. */ if (pid == 0) { /* Child */ close(xcb_get_file_descriptor(conn)); raise_loop(win); exit(EXIT_SUCCESS); } cursor = create_cursor(conn, screen, win, curs_choice); grab_pointer_and_keyboard(conn, screen, cursor); /* Load the keymap again to sync the current modifier state. Since we first * loaded the keymap, there might have been changes, but starting from now, * we should get all key presses/releases due to having grabbed the * keyboard. */ (void)load_keymap(); /* Initialize the libev event loop. */ main_loop = EV_DEFAULT; if (main_loop == NULL) errx(EXIT_FAILURE, "Could not initialize libev. Bad LIBEV_FLAGS?\n"); struct ev_io *xcb_watcher = calloc(sizeof(struct ev_io), 1); struct ev_check *xcb_check = calloc(sizeof(struct ev_check), 1); struct ev_prepare *xcb_prepare = calloc(sizeof(struct ev_prepare), 1); ev_io_init(xcb_watcher, xcb_got_event, xcb_get_file_descriptor(conn), EV_READ); ev_io_start(main_loop, xcb_watcher); ev_check_init(xcb_check, xcb_check_cb); ev_check_start(main_loop, xcb_check); ev_prepare_init(xcb_prepare, xcb_prepare_cb); ev_prepare_start(main_loop, xcb_prepare); /* Invoke the event callback once to catch all the events which were * received up until now. ev will only pick up new events (when the X11 * file descriptor becomes readable). */ ev_invoke(main_loop, xcb_check, 0); ev_loop(main_loop, 0); }
int main(void) { fd_set descriptors; char socket_path[BUFSIZ]; int sock_fd, ret_fd, dpy_fd, sel, n; struct sockaddr_un sock_address; char msg[BUFSIZ] = {0}; char rsp[BUFSIZ] = {0}; xcb_generic_event_t *event; running = true; dpy = xcb_connect(NULL, &default_screen); if (xcb_connection_has_error(dpy)) die("error: cannot open display\n"); setup(); register_events(); dpy_fd = xcb_get_file_descriptor(dpy); char *sp = getenv(SOCKET_ENV_VAR); strncpy(socket_path, (sp == NULL ? DEFAULT_SOCKET_PATH : sp), sizeof(socket_path)); sock_address.sun_family = AF_UNIX; strncpy(sock_address.sun_path, socket_path, sizeof(sock_address.sun_path)); unlink(socket_path); sock_fd = socket(AF_UNIX, SOCK_STREAM, 0); if (sock_fd == -1) die("error: could not create socket\n"); bind(sock_fd, (struct sockaddr *) &sock_address, sizeof(sock_address)); listen(sock_fd, SOMAXCONN); sel = MAX(sock_fd, dpy_fd) + 1; load_settings(); run_autostart(); ewmh_update_wm_name(); update_root_dimensions(); while (running) { xcb_flush(dpy); FD_ZERO(&descriptors); FD_SET(sock_fd, &descriptors); FD_SET(dpy_fd, &descriptors); if (select(sel, &descriptors, NULL, NULL, NULL)) { if (FD_ISSET(sock_fd, &descriptors)) { ret_fd = accept(sock_fd, NULL, 0); if (ret_fd > 0 && (n = recv(ret_fd, msg, sizeof(msg), 0)) > 0) { msg[n] = '\0'; process_message(msg, rsp); send(ret_fd, rsp, strlen(rsp), 0); close(ret_fd); } } if (FD_ISSET(dpy_fd, &descriptors)) { while ((event = xcb_poll_for_event(dpy)) != NULL) { handle_event(event); free(event); } } } if (xcb_connection_has_error(dpy)) { die("connection has errors\n"); } } close(sock_fd); xcb_ewmh_connection_wipe(ewmh); free(ewmh); xcb_flush(dpy); xcb_disconnect(dpy); return 0; }
int main() { uint8_t xrandr; struct pollfd poll_fd; fd_set set; int fd; int retval; int timeout; setlocale (LC_ALL, ""); // bindtextdomain (PACKAGE, LOCALEDIR); // textdomain (PACKAGE); printf("TabletWM version 0.25\n"); init_tabletwm(); uint32_t v[]={XCB_EVENT_MASK_SUBSTRUCTURE_NOTIFY|XCB_EVENT_MASK_SUBSTRUCTURE_REDIRECT}; xcb_change_window_attributes(conn,scr->root,XCB_CW_EVENT_MASK,v); support_capture_key(XCB_MOD_MASK_CONTROL,23); // Ctrl+TAB support_capture_key(XCB_MOD_MASK_1,23); // Alt+TAB support_capture_key(XCB_MOD_MASK_1,70); // Alt+F4 support_capture_key(XCB_MOD_MASK_ANY,135); // MENU key (between the right WINDOWS key and the right Ctrl key) support_capture_key(XCB_MOD_MASK_ANY,124); // POWER key //xcb_grab_key(conn,0,scr->root,XCB_MOD_MASK_ANY,XCB_GRAB_ANY,XCB_GRAB_MODE_ASYNC,XCB_GRAB_MODE_ASYNC); #ifdef DEBUG support_capture_key(XCB_MOD_MASK_1,71); // Alt+F5 for VALGRIND tests #endif /* detect changes in screen size with xrandr */ xcb_randr_query_version_reply_t *r=xcb_randr_query_version_reply(conn,xcb_randr_query_version(conn,1,1),0); if (r) { xcb_randr_select_input(conn,scr->root,XCB_RANDR_NOTIFY_MASK_SCREEN_CHANGE); const xcb_query_extension_reply_t *r2=xcb_get_extension_data(conn,&xcb_randr_id); xrandr=r2->first_event; } free(r); xcb_flush(conn); xcb_generic_event_t *e; keep_running=1; support_launch_manager(); fd = xcb_get_file_descriptor(conn); while(keep_running) { poll_fd.fd=fd; poll_fd.events=POLLIN; poll_fd.revents=0; if (key_win.possition!=0) { retval = poll(&poll_fd,1,2000); // refresh every two seconds if the bar is visible } else { retval = poll(&poll_fd,1,-1); // just wait for an event when the bar is not visible } if (retval==0) { menuwin_expose(NULL); // each 10 seconds of inactivity, refresh the user bar to keep the clock and indicators updated continue; } while(e=xcb_poll_for_event(conn)) { uint8_t r=e->response_type&~0x80; if (r>=xrandr) { printf("XRandR\n"); switch(r-xrandr) { case(XCB_RANDR_SCREEN_CHANGE_NOTIFY): action_xrandr_screen_change_notify(e); break; default: printf("XRandR unknown: %d\n",r-xrandr); break; } } else { switch(r) { case(XCB_KEY_RELEASE): action_key(e); break; case (XCB_CREATE_NOTIFY): //xcb_create_notify_event_t *ee=(xcb_create_notify_event_t *)e; break; case(XCB_UNMAP_NOTIFY): action_unmap_notify(e); break; case(XCB_DESTROY_NOTIFY): action_destroy_notify(e); break; case(XCB_MAP_REQUEST): action_map_request(e); break; case(XCB_MAP_NOTIFY): case(XCB_MAPPING_NOTIFY): support_send_dock_up(NULL,NULL); // ensure that the dock is always on top break; case(XCB_CONFIGURE_NOTIFY): action_configure_notify(e); break; case(XCB_CONFIGURE_REQUEST): action_configure_request(e); break; case(XCB_CIRCULATE_REQUEST): //xcb_circulate_request_event_t *ee=(xcb_circulate_request_event_t *)e; break; case(XCB_EXPOSE): action_expose(e); break; case(XCB_ENTER_NOTIFY): action_mouse_enter(e); break; case(XCB_LEAVE_NOTIFY): action_mouse_leave(e); break; case(XCB_BUTTON_RELEASE): action_mouse_click(e); break; case(0): { xcb_generic_error_t *ee=(xcb_generic_error_t *)e; printf("error event type %d\n",ee->error_code); } break; default: printf("unhandled event type %d\n",e->response_type); break; } } free(e); } } destroy_tabletwm(); xcb_disconnect(conn); return(0); }
int main(int argc, char *argv[]) { if (argc == 2 && strcmp(argv[1], "-v") == 0) { printf("%s\n", VERSION); exit(EXIT_SUCCESS); } fd_set descriptors; char socket_path[MAXLEN]; int sock_fd, ret_fd, dpy_fd, sel, n; struct sockaddr_un sock_address; size_t rsplen = 0; char msg[BUFSIZ] = {0}; char rsp[BUFSIZ] = {0}; xcb_generic_event_t *event; running = true; dpy = xcb_connect(NULL, &default_screen); if (xcb_connection_has_error(dpy)) err("error: cannot open display\n"); setup(); register_events(); dpy_fd = xcb_get_file_descriptor(dpy); char *sp = getenv(SOCKET_ENV_VAR); strncpy(socket_path, (sp == NULL ? DEFAULT_SOCKET_PATH : sp), sizeof(socket_path)); sock_address.sun_family = AF_UNIX; strncpy(sock_address.sun_path, socket_path, sizeof(sock_address.sun_path)); unlink(socket_path); sock_fd = socket(AF_UNIX, SOCK_STREAM, 0); if (sock_fd == -1) err("error: could not create socket\n"); bind(sock_fd, (struct sockaddr *) &sock_address, sizeof(sock_address)); listen(sock_fd, SOMAXCONN); sel = MAX(sock_fd, dpy_fd) + 1; load_settings(); run_autostart(); grab_buttons(); ewmh_update_wm_name(); while (running) { xcb_flush(dpy); FD_ZERO(&descriptors); FD_SET(sock_fd, &descriptors); FD_SET(dpy_fd, &descriptors); if (select(sel, &descriptors, NULL, NULL, NULL)) { if (FD_ISSET(sock_fd, &descriptors)) { ret_fd = accept(sock_fd, NULL, 0); if (ret_fd > 0 && (n = recv(ret_fd, msg, sizeof(msg), 0)) > 0) { msg[n] = '\0'; process_message(msg, rsp); rsplen = strlen(rsp); if (rsp[rsplen - 1] == '\n') rsp[--rsplen] = '\0'; send(ret_fd, rsp, rsplen, 0); close(ret_fd); rsp[0] = '\0'; } } if (FD_ISSET(dpy_fd, &descriptors)) { while ((event = xcb_poll_for_event(dpy)) != NULL) { handle_event(event); free(event); } } } if (xcb_connection_has_error(dpy)) { err("connection has errors\n"); } } close(sock_fd); xcb_ewmh_connection_wipe(ewmh); free(ewmh); xcb_flush(dpy); xcb_disconnect(dpy); return 0; }