Example #1
0
/** Call before exiting.
 */
void
awesome_atexit(bool restart)
{
    int screen_nbr, nscreens;

    if(globalconf.hooks.exit != LUA_REFNIL)
        luaA_dofunction_from_registry(globalconf.L, globalconf.hooks.exit, 0, 0);

    lua_pushboolean(globalconf.L, restart);
    signal_object_emit(globalconf.L, &global_signals, "exit", 1);

    a_dbus_cleanup();

    /* do this only for real screen */
    const xcb_setup_t *setup = xcb_get_setup(globalconf.connection);
    nscreens = setup ? xcb_setup_roots_length(setup) : -1;
    for(screen_nbr = 0;
        screen_nbr < nscreens;
        screen_nbr++)
        systray_cleanup(0, screen_nbr); //FIXME: Clean physical screens

    /* Close Lua */
    lua_close(globalconf.L);

    xcb_flush(globalconf.connection);

    /* Disconnect *after* closing lua */
    xcb_disconnect(globalconf.connection);

    ev_default_destroy();
}
Example #2
0
/** Grab key on the root windows.
 * \param k The keybinding.
 */
void
window_root_grabkey(keybinding_t *k)
{
    int phys_screen = 0;
    int nscreen = xcb_setup_roots_length(xcb_get_setup(globalconf.connection));
    xcb_screen_t *s;
    xcb_keycode_t kc;

    if((kc = k->keycode)
       || (k->keysym
           && (kc = xcb_key_symbols_get_keycode(globalconf.keysyms, k->keysym))))
        do
        {
            s = xutil_screen_get(globalconf.connection, phys_screen);
            xcb_grab_key(globalconf.connection, true, s->root,
                         k->mod, kc, XCB_GRAB_MODE_ASYNC, XCB_GRAB_MODE_ASYNC);
            xcb_grab_key(globalconf.connection, true, s->root,
                         k->mod | XCB_MOD_MASK_LOCK, kc, XCB_GRAB_MODE_ASYNC, XCB_GRAB_MODE_ASYNC);
            xcb_grab_key(globalconf.connection, true, s->root,
                         k->mod | globalconf.numlockmask, kc, XCB_GRAB_MODE_ASYNC, XCB_GRAB_MODE_ASYNC);
            xcb_grab_key(globalconf.connection, true, s->root,
                         k->mod | globalconf.numlockmask | XCB_MOD_MASK_LOCK, kc, XCB_GRAB_MODE_ASYNC,
                         XCB_GRAB_MODE_ASYNC);
        phys_screen++;
        } while(phys_screen < nscreen);
}
Example #3
0
int iterate_screens(int, char **)
{
    xcb_connection_t *conn = xcb_connect(0, 0);
    xcb_screen_iterator_t i = xcb_setup_roots_iterator(xcb_get_setup(conn));
    std::vector<xcb_screen_t> screens;
    std::copy(i, xcb::end(i), std::back_inserter(screens));
    assert(screens.size() == xcb_setup_roots_length(xcb_get_setup(conn)));
    return EXIT_SUCCESS;
}
Example #4
0
void scan_windows(void)
{
    const int screens_len = xcb_setup_roots_length(xcb_get_setup(wm_conf.connection));
    int screen_idx;
    xcb_window_t root_wins[screens_len];
    xcb_query_tree_cookie_t root_tree_cookies[screens_len];

    /* request window trees for the root window of each screen */
    for (screen_idx = 0; screen_idx < screens_len; ++screen_idx) {
        xcb_screen_t *screen = xcb_aux_get_screen(wm_conf.connection, screen_idx);
        root_wins[screen_idx] = screen->root;
        root_tree_cookies[screen_idx] = xcb_query_tree_unchecked(wm_conf.connection,
                                                                 root_wins[screen_idx]);
    }

    xcb_query_tree_reply_t *root_tree_replies[screens_len];
    xcb_window_t *wins;
    int wins_len;

    /* collect replies */
    for (screen_idx = 0; screen_idx < screens_len; ++screen_idx) {
        root_tree_replies[screen_idx] = xcb_query_tree_reply(wm_conf.connection,
                                                             root_tree_cookies[screen_idx],
                                                             NULL);
        wins = xcb_query_tree_children(root_tree_replies[screen_idx]);
        if (!wins)
            fprintf(stderr, "failed to get child tree for window %u\n", root_wins[screen_idx]);
        wins_len = xcb_query_tree_children_length(root_tree_replies[screen_idx]);
        fprintf(stderr, "root window %u has %d children\n", root_wins[screen_idx], wins_len);

        fprintf(stderr, "examining children\n");
        xcb_window_t child_win;
        int i;
        for (i = 0; i < wins_len; ++i) {
            child_win = wins[i];
            fprintf(stderr, "  child window %u\n", child_win);
            client_t *client = find_client(child_win);
            if (!client) {
                client = client_init(client_alloc());
                client->window = child_win;
                sglib_client_t_add(&client_list, client);
            }
            read_client_geometry(client);
        }
    }

    for (screen_idx = 0; screen_idx < screens_len; ++screen_idx)
        free(root_tree_replies[screen_idx]);
}
Example #5
0
/** Refresh all systrays registrations per physical screen
 */
void
systray_refresh()
{
    int nscreen = xcb_setup_roots_length(xcb_get_setup(globalconf.connection));

    for(int phys_screen = 0; phys_screen < nscreen; phys_screen++)
    {
        bool has_systray = false;
        foreach(w, globalconf.wiboxes)
            if(phys_screen == (*w)->ctx.phys_screen && (*w)->has_systray)
                /* Can't use "break" with foreach() :( */
                has_systray = true;

        if(has_systray)
            systray_register(phys_screen);
        else
            systray_cleanup(phys_screen);
    }
}
/** Grab the mouse.
 * \param cursor The cursor to use while grabbing.
 * \return True if mouse was grabbed.
 */
static bool
mousegrabber_grab(xcb_cursor_t cursor)
{
    xcb_window_t root = XCB_NONE;

    for(int screen = 0;
        screen < xcb_setup_roots_length(xcb_get_setup(globalconf.connection));
        screen++)
    {
        int16_t x, y;
        uint16_t mask;

        root = xutil_screen_get(globalconf.connection, screen)->root;
        if(mouse_query_pointer(root, &x, &y, NULL, &mask))
            break;
    }

    for(int i = 1000; i; i--)
    {
        xcb_grab_pointer_reply_t *grab_ptr_r;
        xcb_grab_pointer_cookie_t grab_ptr_c =
            xcb_grab_pointer_unchecked(globalconf.connection, false, root,
                                       XCB_EVENT_MASK_BUTTON_PRESS
                                       | XCB_EVENT_MASK_BUTTON_RELEASE
                                       | XCB_EVENT_MASK_POINTER_MOTION,
                                       XCB_GRAB_MODE_ASYNC,
                                       XCB_GRAB_MODE_ASYNC,
                                       root, cursor, XCB_CURRENT_TIME);

        if((grab_ptr_r = xcb_grab_pointer_reply(globalconf.connection, grab_ptr_c, NULL)))
        {
            p_delete(&grab_ptr_r);
            return true;
        }
        usleep(1000);
    }
    return false;
}
Example #7
0
File: root.c Project: paul/awesome
/** Get or set global key bindings.
 * This binding will be available when you'll press keys on root window.
 * \param L The Lua VM state.
 * \return The number of element pushed on stack.
 * \luastack
 * \lparam An array of key bindings objects, or nothing.
 * \lreturn The array of key bindings objects of this client.
 */
static int
luaA_root_keys(lua_State *L)
{
    if(lua_gettop(L) == 1)
    {
        luaA_checktable(L, 1);

        foreach(key, globalconf.keys)
            luaA_object_unref(globalconf.L, *key);

        key_array_wipe(&globalconf.keys);
        key_array_init(&globalconf.keys);

        lua_pushnil(L);
        while(lua_next(L, 1))
            key_array_append(&globalconf.keys, luaA_object_ref_class(L, -1, &key_class));

        int nscreen = xcb_setup_roots_length(xcb_get_setup(globalconf.connection));

        for(int phys_screen = 0; phys_screen < nscreen; phys_screen++)
        {
            xcb_screen_t *s = xutil_screen_get(globalconf.connection, phys_screen);
            xcb_ungrab_key(globalconf.connection, XCB_GRAB_ANY, s->root, XCB_BUTTON_MASK_ANY);
            xwindow_grabkeys(s->root, &globalconf.keys);
        }

        return 1;
    }

    lua_createtable(L, globalconf.keys.len, 0);
    for(int i = 0; i < globalconf.keys.len; i++)
    {
        luaA_object_push(L, globalconf.keys.tab[i]);
        lua_rawseti(L, -2, i + 1);
    }

    return 1;
}
Example #8
0
File: root.c Project: paul/awesome
/** Set the root cursor.
 * \param L The Lua VM state.
 * \return The number of element pushed on stack.
 * \luastack
 * \lparam A X cursor name.
 */
static int
luaA_root_cursor(lua_State *L)
{
    const char *cursor_name = luaL_checkstring(L, 1);
    uint16_t cursor_font = xcursor_font_fromstr(cursor_name);

    if(cursor_font)
    {
        uint32_t change_win_vals[] = { xcursor_new(globalconf.connection, cursor_font) };

        for(int screen_nbr = 0;
            screen_nbr < xcb_setup_roots_length(xcb_get_setup(globalconf.connection));
            screen_nbr++)
            xcb_change_window_attributes(globalconf.connection,
                                         xutil_screen_get(globalconf.connection, screen_nbr)->root,
                                         XCB_CW_CURSOR,
                                         change_win_vals);
    }
    else
        luaA_warn(L, "invalid cursor %s", cursor_name);

    return 0;
}
Example #9
0
File: event.c Project: paul/awesome
/** The button press event handler.
 * \param data The type of mouse event.
 * \param connection The connection to the X server.
 * \param ev The event.
 */
static int
event_handle_button(void *data, xcb_connection_t *connection, xcb_button_press_event_t *ev)
{
    int screen;
    const int nb_screen = xcb_setup_roots_length(xcb_get_setup(connection));
    client_t *c;
    wibox_t *wibox;

    if(event_handle_mousegrabber(ev->root_x, ev->root_y, 1 << (ev->detail - 1 + 8)))
        return 0;

    /* ev->state is
     * button status (8 bits) + modifiers status (8 bits)
     * we don't care for button status that we get, especially on release, so
     * drop them */
    ev->state &= 0x00ff;

    if((wibox = wibox_getbywin(ev->event))
       || (wibox = wibox_getbywin(ev->child)))
    {
        /* If the wibox is child, then x,y are
         * relative to root window */
        if(wibox->window == ev->child)
        {
            ev->event_x -= wibox->geometry.x;
            ev->event_y -= wibox->geometry.y;
        }

        /* Push the wibox */
        luaA_object_push(globalconf.L, wibox);
        /* Duplicate the wibox */
        lua_pushvalue(globalconf.L, -1);
        /* Handle the button event on it */
        event_button_callback(ev, &wibox->buttons, -1, 1, NULL);

        /* then try to match a widget binding */
        widget_t *w = widget_getbycoords(wibox->orientation, &wibox->widgets,
                                         wibox->geometry.width,
                                         wibox->geometry.height,
                                         &ev->event_x, &ev->event_y);
        if(w)
        {
            /* Push widget (the wibox is already on stack) */
            luaA_object_push_item(globalconf.L, -1, w);
            /* Move widget before wibox */
            lua_insert(globalconf.L, -2);
            event_button_callback(ev, &w->buttons, -2, 2, NULL);
        }
        else
            /* Remove the wibox, we did not use it */
            lua_pop(globalconf.L, 1);

    }
    else if((c = client_getbywin(ev->event)))
    {
        luaA_object_push(globalconf.L, c);
        event_button_callback(ev, &c->buttons, -1, 1, NULL);
        xcb_allow_events(globalconf.connection,
                         XCB_ALLOW_REPLAY_POINTER,
                         XCB_CURRENT_TIME);
    }
    else if(ev->child == XCB_NONE)
        for(screen = 0; screen < nb_screen; screen++)
            if(xutil_screen_get(connection, screen)->root == ev->event)
            {
                event_button_callback(ev, &globalconf.buttons, 0, 0, NULL);
                return 0;
            }

    return 0;
}
Example #10
0
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;
}
Example #11
0
/** Scan X to find windows to manage.
 */
static void
scan(xcb_query_tree_cookie_t tree_c[])
{
    int i, x_screen, tree_c_len;
    const int screen_max = xcb_setup_roots_length(xcb_get_setup(globalconf.connection));
    xcb_query_tree_reply_t *tree_r;
    xcb_window_t *wins = NULL;
    xcb_get_window_attributes_reply_t *attr_r;
    xcb_get_geometry_reply_t *geom_r;
    long state;

    for(x_screen = 0; x_screen < screen_max; x_screen++)
    {
        tree_r = xcb_query_tree_reply(globalconf.connection,
                                      tree_c[x_screen],
                                      NULL);

        if(!tree_r)
            continue;

        /* Get the tree of the children windows of the current root window */
        if(!(wins = xcb_query_tree_children(tree_r)))
            fatal("cannot get tree children");

        tree_c_len = xcb_query_tree_children_length(tree_r);
        xcb_get_window_attributes_cookie_t attr_wins[tree_c_len];
        xcb_get_property_cookie_t state_wins[tree_c_len];

        for(i = 0; i < tree_c_len; i++)
        {
            attr_wins[i] = xcb_get_window_attributes_unchecked(globalconf.connection,
                                                               wins[i]);

            state_wins[i] = window_state_get_unchecked(wins[i]);
        }

        xcb_get_geometry_cookie_t *geom_wins[tree_c_len];

        for(i = 0; i < tree_c_len; i++)
        {
            attr_r = xcb_get_window_attributes_reply(globalconf.connection,
                                                     attr_wins[i],
                                                     NULL);

            state = window_state_get_reply(state_wins[i]);

            if(!attr_r || attr_r->override_redirect
               || attr_r->map_state == XCB_MAP_STATE_UNMAPPED
               || state == XCB_ICCCM_WM_STATE_WITHDRAWN)
            {
                geom_wins[i] = NULL;
                p_delete(&attr_r);
                continue;
            }

            p_delete(&attr_r);

            /* Get the geometry of the current window */
            geom_wins[i] = p_alloca(xcb_get_geometry_cookie_t, 1);
            *(geom_wins[i]) = xcb_get_geometry_unchecked(globalconf.connection, wins[i]);
        }

        for(i = 0; i < tree_c_len; i++)
        {
            if(!geom_wins[i] || !(geom_r = xcb_get_geometry_reply(globalconf.connection,
                                                                  *(geom_wins[i]), NULL)))
                continue;

            /* The window can be mapped, so force it to be undrawn for startup */
            xcb_unmap_window(globalconf.connection, wins[i]);

            client_manage(wins[i], geom_r,
                          phys_screen_getbycoord(geom_r->x, geom_r->y, geom_r->root),
                          x_screen, true);

            p_delete(&geom_r);
        }

        p_delete(&tree_r);
    }
}
Example #12
0
/** 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;
}
Example #13
0
/**
 * The x server was changed
 */
static bool xshm_server_changed(obs_properties_t *props,
		obs_property_t *p, obs_data_t *settings)
{
	UNUSED_PARAMETER(p);

	bool advanced           = obs_data_get_bool(settings, "advanced");
	int_fast32_t old_screen = obs_data_get_int(settings, "screen");
	const char *server      = obs_data_get_string(settings, "server");
	obs_property_t *screens = obs_properties_get(props, "screen");

	/* we want a real NULL here in case there is no string here */
	server = (advanced && *server) ? server : NULL;

	obs_property_list_clear(screens);

	xcb_connection_t *xcb = xcb_connect(server, NULL);
	if (!xcb || xcb_connection_has_error(xcb)) {
		obs_property_set_enabled(screens, false);
		return true;
	}

	struct dstr screen_info;
	dstr_init(&screen_info);
	bool xinerama = xinerama_is_active(xcb);
	int_fast32_t count = (xinerama) ?
			xinerama_screen_count(xcb) :
			xcb_setup_roots_length(xcb_get_setup(xcb));

	for (int_fast32_t i = 0; i < count; ++i) {
		int_fast32_t x, y, w, h;
		x = y = w = h = 0;

		if (xinerama)
			xinerama_screen_geo(xcb, i, &x, &y, &w, &h);
		else
			x11_screen_geo(xcb, i, &w, &h);

		dstr_printf(&screen_info, "Screen %"PRIuFAST32" (%"PRIuFAST32
				"x%"PRIuFAST32" @ %"PRIuFAST32
				",%"PRIuFAST32")", i, w, h, x, y);

		obs_property_list_add_int(screens, screen_info.array, i);
	}

	/* handle missing screen */
	if (old_screen + 1 > count) {
		dstr_printf(&screen_info, "Screen %"PRIuFAST32" (not found)",
				old_screen);
		size_t index = obs_property_list_add_int(screens,
				screen_info.array, old_screen);
		obs_property_list_item_disable(screens, index, true);

	}

	dstr_free(&screen_info);

	xcb_disconnect(xcb);
	obs_property_set_enabled(screens, true);

	return true;
}
Example #14
0
/** The button press event handler.
 * \param data The type of mouse event.
 * \param connection The connection to the X server.
 * \param ev The event.
 */
static int
event_handle_button(void *data, xcb_connection_t *connection, xcb_button_press_event_t *ev)
{
    int screen;
    const int nb_screen = xcb_setup_roots_length(xcb_get_setup(connection));
    client_t *c;
    wibox_t *wibox;

    /* ev->state is
     * button status (8 bits) + modifiers status (8 bits)
     * we don't care for button status that we get, especially on release, so
     * drop them */
    ev->state &= 0x00ff;

    event_handle_mousegrabber(ev->root_x, ev->root_y, ev->state);

    if((wibox = wibox_getbywin(ev->event))
       || (wibox = wibox_getbywin(ev->child)))
    {
        /* If the wibox is child, then x,y are
         * relative to root window */
        if(wibox->sw.window == ev->child)
        {
            ev->event_x -= wibox->sw.geometry.x;
            ev->event_y -= wibox->sw.geometry.y;
        }

        /* check if we match a binding on the wibox */
        button_array_t *b = &wibox->buttons;

        for(int i = 0; i < b->len; i++)
            if(ev->detail == b->tab[i]->button
               && ev->state == b->tab[i]->mod)
                switch(ev->response_type)
                {
                  case XCB_BUTTON_PRESS:
                    if(b->tab[i]->press != LUA_REFNIL)
                    {
                        wibox_push(globalconf.L, wibox);
                        luaA_dofunction(globalconf.L, b->tab[i]->press, 1, 0);
                    }
                    break;
                  case XCB_BUTTON_RELEASE:
                    if(b->tab[i]->release != LUA_REFNIL)
                    {
                        wibox_push(globalconf.L, wibox);
                        luaA_dofunction(globalconf.L, b->tab[i]->release, 1, 0);
                    }
                    break;
                }

        /* then try to match a widget binding */
        widget_t *w = widget_getbycoords(wibox->position, &wibox->widgets,
                                         wibox->sw.geometry.width,
                                         wibox->sw.geometry.height,
                                         &ev->event_x, &ev->event_y);
        if(w)
        {
            b = &w->buttons;

            for(int i = 0; i < b->len; i++)
                if(ev->detail == b->tab[i]->button
                   && ev->state == b->tab[i]->mod)
                    switch(ev->response_type)
                    {
                      case XCB_BUTTON_PRESS:
                        if(b->tab[i]->press != LUA_REFNIL)
                        {
                            wibox_push(globalconf.L, wibox);
                            luaA_dofunction(globalconf.L, b->tab[i]->press, 1, 0);
                        }
                        break;
                      case XCB_BUTTON_RELEASE:
                        if(b->tab[i]->release != LUA_REFNIL)
                        {
                            wibox_push(globalconf.L, wibox);
                            luaA_dofunction(globalconf.L, b->tab[i]->release, 1, 0);
                        }
                        break;
                    }
        }
        /* return even if no widget match */
        return 0;
    }
    else if((c = client_getbywin(ev->event)))
    {
        event_handle_mouse_button(c, ev->response_type, ev->detail, ev->state, &c->buttons);
        xcb_allow_events(globalconf.connection,
                         XCB_ALLOW_REPLAY_POINTER,
                         XCB_CURRENT_TIME);
    }
    else if(ev->child == XCB_NONE)
    {
        for(screen = 0; screen < nb_screen; screen++)
            if(xutil_screen_get(connection, screen)->root == ev->event)
            {
                event_handle_mouse_button(NULL, ev->response_type, ev->detail, ev->state, &globalconf.buttons);
                return 0;
            }
    }

    return 0;
}
/**
 * sn_xcb_display_new:
 * @xdisplay: an X window system connection
 * @push_trap_func: function to push an X error trap
 * @pop_trap_func: function to pop an X error trap
 *
 * Creates a new #SnDisplay object, containing
 * data that libsn associates with an X connection.
 *
 * @push_trap_func should be a function that causes X errors to be
 * ignored until @pop_trap_func is called as many times as
 * @push_trap_func has been called. (Nested push/pop pairs must be
 * supported.)
 * These functions are used to avoid X errors due to BadWindow and
 * such.
 *
 * Return value: the new #SnDisplay
 **/
SnDisplay*
sn_xcb_display_new (xcb_connection_t          *xconnection,
                    SnXcbDisplayErrorTrapPush  push_trap_func,
                    SnXcbDisplayErrorTrapPop   pop_trap_func)
{
  SnDisplay *display;
  int i;

  /* Get all atoms we will need in the future */
  xcb_intern_atom_cookie_t atom_utf8_string_c =
    xcb_intern_atom(xconnection, FALSE,
                    sizeof("UTF8_STRING") - 1, "UTF8_STRING");

  xcb_intern_atom_cookie_t atom_net_startup_info_begin_c =
    xcb_intern_atom(xconnection, FALSE,
                    sizeof("_NET_STARTUP_INFO_BEGIN") - 1,
                    "_NET_STARTUP_INFO_BEGIN");

  xcb_intern_atom_cookie_t atom_net_startup_info_c =
    xcb_intern_atom(xconnection, FALSE,
                    sizeof("_NET_STARTUP_INFO") - 1, "_NET_STARTUP_INFO");

  xcb_intern_atom_cookie_t atom_net_startup_id_c =
    xcb_intern_atom(xconnection, FALSE,
                    sizeof("_NET_STARTUP_ID") - 1, "_NET_STARTUP_ID");

  display = sn_new0 (SnDisplay, 1);

  display->xconnection = xconnection;
  display->n_screens = xcb_setup_roots_length (xcb_get_setup (xconnection));
  display->screens = sn_new (xcb_screen_t*, display->n_screens);
  display->refcount = 1;

  display->xcb_push_trap_func = push_trap_func;
  display->xcb_pop_trap_func = pop_trap_func;

  for (i = 0; i < display->n_screens; ++i)
    display->screens[i] = xcb_aux_get_screen(xconnection, i);

  xcb_intern_atom_reply_t *atom_reply;

  atom_reply = xcb_intern_atom_reply(display->xconnection,
                                     atom_utf8_string_c,
                                     NULL);
  display->UTF8_STRING = atom_reply->atom;
  free(atom_reply);

  atom_reply = xcb_intern_atom_reply(display->xconnection,
                                     atom_net_startup_info_begin_c,
                                     NULL);
  display->NET_STARTUP_INFO_BEGIN = atom_reply->atom;
  free(atom_reply);

  atom_reply = xcb_intern_atom_reply(display->xconnection,
                                     atom_net_startup_info_c,
                                     NULL);
  display->NET_STARTUP_INFO = atom_reply->atom;
  free(atom_reply);

  atom_reply = xcb_intern_atom_reply(display->xconnection,
                                     atom_net_startup_id_c,
                                     NULL);
  display->NET_STARTUP_ID = atom_reply->atom;
  free(atom_reply);

  return display;
}