Ejemplo n.º 1
0
/**
 * sn_xcb_display_process_event:
 * @display: a display
 * @xevent: X event
 *
 * libsn should be given a chance to see all X events by passing them
 * to this function. If the event was a property notify or client
 * message related to the launch feedback protocol, the
 * sn_display_process_event() returns true. Calling
 * sn_display_process_event() is not currently required for launchees,
 * only launchers and launch feedback displayers. The function returns
 * false for mapping, unmapping, window destruction, and selection
 * events even if they were involved in launch feedback.
 *
 * Return value: true if the event was a property notify or client message involved in launch feedback
 **/
sn_bool_t
sn_xcb_display_process_event (SnDisplay           *display,
                              xcb_generic_event_t *xevent)
{
  sn_bool_t retval;

  retval = FALSE;

  if (sn_internal_monitor_process_event (display))
    retval = TRUE;

  switch(XCB_EVENT_RESPONSE_TYPE(xevent))
  {
    case XCB_CLIENT_MESSAGE:
      {
        xcb_client_message_event_t *ev = (xcb_client_message_event_t *) xevent;
        if (sn_internal_xmessage_process_client_message (display,
                                                         ev->window,
                                                         ev->type,
                                                         (const char *) ev->data.data8))
          retval = TRUE;
      }
      break;
    default:
      break;
  }

  return retval;
}
Ejemplo n.º 2
0
Archivo: leaf.c Proyecto: shaoner/leaf
static leaf_error_t leaf_run()
{
	xcb_generic_event_t *event = NULL;
	int etype;
	leaf_error_t status = ERR_NONE;

	/* Start main loop */
	gconf.running = true;
	do {
		event = xcb_poll_for_event(gconf.conn);
		if (!event) {
            if (xcb_connection_has_error(gconf.conn))
	            return ERR_CONN;
			continue;
		}
		etype = XCB_EVENT_RESPONSE_TYPE(event);

		/* Only for debug prupose */
		print_event(etype);

		/* Execute specific event handler */
		if (geventhandlers[etype])
			if (geventhandlers[etype](event) != EVENT_ERR_NONE)
				status = ERR_EVENT;
		free(event);
	} while (gconf.running && status == ERR_NONE);

	return status;
}
Ejemplo n.º 3
0
static void
a_xcb_check_cb(EV_P_ ev_check *w, int revents)
{
    xcb_generic_event_t *mouse = NULL, *event;

    while((event = xcb_poll_for_event(globalconf.connection)))
    {
        /* We will treat mouse events later.
         * We cannot afford to treat all mouse motion events,
         * because that would be too much CPU intensive, so we just
         * take the last we get after a bunch of events. */
        if(XCB_EVENT_RESPONSE_TYPE(event) == XCB_MOTION_NOTIFY)
        {
            p_delete(&mouse);
            mouse = event;
        }
        else
        {
            event_handle(event);
            p_delete(&event);
        }
    }

    if(mouse)
    {
        event_handle(mouse);
        p_delete(&mouse);
    }
}
Ejemplo n.º 4
0
static void kt_xcb_event_handler(xcb_connection_t *c)
{
        xcb_generic_event_t *event = NULL;

        while((event = xcb_poll_for_event(c))) {
                guint8 response_type;

                response_type = XCB_EVENT_RESPONSE_TYPE(event);
                if (response_type != 0) {
                        handle_x_event(response_type, event);
                }
        }

        xcb_flush(c);
}
Ejemplo n.º 5
0
int main(void)
{
	xcb_connection_t *dpy = xcb_connect(NULL, NULL);
	if (dpy == NULL) {
		fprintf(stderr, "Can't connect to X.\n");
		return EXIT_FAILURE;
	}
	xcb_atom_t WM_PROTOCOLS, WM_DELETE_WINDOW;
	if (!get_atom(dpy, "WM_PROTOCOLS", &WM_PROTOCOLS) ||
	    !get_atom(dpy, "WM_DELETE_WINDOW", &WM_DELETE_WINDOW)) {
		fprintf(stderr, "Can't get required atoms.\n");
		xcb_disconnect(dpy);
		return EXIT_FAILURE;
	}
	xcb_screen_t *screen = xcb_setup_roots_iterator(xcb_get_setup(dpy)).data;
	if (screen == NULL) {
		fprintf(stderr, "Can't get current screen.\n");
		xcb_disconnect(dpy);
		return EXIT_FAILURE;
	}
	xcb_window_t win = xcb_generate_id(dpy);
	uint32_t mask = XCB_CW_BACK_PIXEL | XCB_CW_EVENT_MASK;
	uint32_t values[] = {0xff111111, XCB_EVENT_MASK_EXPOSURE};
	xcb_create_window(dpy, XCB_COPY_FROM_PARENT, win, screen->root, 0, 0, 320, 240, 2,
	                  XCB_WINDOW_CLASS_INPUT_OUTPUT, XCB_COPY_FROM_PARENT, mask, values);
	xcb_icccm_set_wm_class(dpy, win, sizeof(TEST_WINDOW_IC), TEST_WINDOW_IC);
	xcb_map_window(dpy, win);
	xcb_flush(dpy);
	xcb_generic_event_t *evt;
	bool running = true;
	while (running && (evt = xcb_wait_for_event(dpy)) != NULL) {
		uint8_t rt = XCB_EVENT_RESPONSE_TYPE(evt);
		if (rt == XCB_CLIENT_MESSAGE)  {
			xcb_client_message_event_t *cme = (xcb_client_message_event_t *) evt;
			if (cme->type == WM_PROTOCOLS && cme->data.data32[0] == WM_DELETE_WINDOW) {
				running = false;
			}
		} else if (rt == XCB_EXPOSE) {
			render_text(dpy, win, 12, 24);
		}
		free(evt);
	}
	xcb_destroy_window(dpy, win);
	xcb_disconnect(dpy);
	return EXIT_SUCCESS;
}
Ejemplo n.º 6
0
Archivo: xtitle.c Proyecto: mmso/xtitle
bool title_changed(xcb_generic_event_t *evt, xcb_window_t *win, xcb_window_t *last_win)
{
    if (XCB_EVENT_RESPONSE_TYPE(evt) == XCB_PROPERTY_NOTIFY) {
        xcb_property_notify_event_t *pne = (xcb_property_notify_event_t *) evt;
        if (pne->atom == ewmh->_NET_ACTIVE_WINDOW) {
            watch(*last_win, false);
            if (get_active_window(win)) {
                watch(*win, true);
                *last_win = *win;
            } else {
                *win = *last_win = XCB_NONE;
            }
            return true;
        } else if (*win != XCB_NONE && pne->window == *win && (pne->atom == ewmh->_NET_WM_NAME || pne->atom == XCB_ATOM_WM_NAME)) {
            return true;
        }
    }
    return false;
}
Ejemplo n.º 7
0
void handle_event(xcb_generic_event_t *evt)
{
	uint8_t resp_type = XCB_EVENT_RESPONSE_TYPE(evt);
	switch (resp_type) {
		case XCB_MAP_REQUEST:
			map_request(evt);
			break;
		case XCB_DESTROY_NOTIFY:
			destroy_notify(evt);
			break;
		case XCB_UNMAP_NOTIFY:
			unmap_notify(evt);
			break;
		case XCB_CLIENT_MESSAGE:
			client_message(evt);
			break;
		case XCB_CONFIGURE_REQUEST:
			configure_request(evt);
			break;
		case XCB_PROPERTY_NOTIFY:
			property_notify(evt);
			break;
		case XCB_ENTER_NOTIFY:
			enter_notify(evt);
			break;
		case XCB_MOTION_NOTIFY:
			motion_notify(evt);
			break;
		case XCB_FOCUS_IN:
			focus_in(evt);
			break;
		case 0:
			process_error(evt);
			break;
		default:
			if (randr && resp_type == randr_base + XCB_RANDR_SCREEN_CHANGE_NOTIFY) {
				update_monitors();
			}
			break;
	}
}
bool FdoSelectionManager::nativeEventFilter(const QByteArray& eventType, void* message, long int* result)
{
    Q_UNUSED(result);

    if (eventType != "xcb_generic_event_t") {
        return false;
    }

    xcb_generic_event_t* ev = static_cast<xcb_generic_event_t *>(message);

    auto responseType = XCB_EVENT_RESPONSE_TYPE(ev);
    if (responseType == XCB_CLIENT_MESSAGE) {
        auto ce = reinterpret_cast<xcb_client_message_event_t *>(ev);
        if (ce->type == Xcb::atoms->opcodeAtom) {
            switch (ce->data.data32[1]) {
                case SYSTEM_TRAY_REQUEST_DOCK:
                    dock(ce->data.data32[2]);
                    return true;
            }
        }
    } else if (responseType == XCB_UNMAP_NOTIFY) {
        auto unmappedWId = reinterpret_cast<xcb_unmap_notify_event_t *>(ev)->window;
        if (m_proxies[unmappedWId]) {
            undock(unmappedWId);
        }
    } else if (responseType == m_damageEventBase + XCB_DAMAGE_NOTIFY) {
        auto damagedWId = reinterpret_cast<xcb_damage_notify_event_t *>(ev)->drawable;
        auto sniProx = m_proxies[damagedWId];

        Q_ASSERT(sniProx);

        if(sniProx) {
            sniProx->update();
            xcb_damage_subtract(QX11Info::connection(), m_damageWatches[damagedWId], XCB_NONE, XCB_NONE);
        }
    }

    return false;
}
Ejemplo n.º 9
0
bool Compositor::nativeEventFilter(const QByteArray &eventType, void *message, long *)
{
    Q_ASSERT(eventType == QByteArrayLiteral("xcb_generic_event_t"));

    auto responseType = XCB_EVENT_RESPONSE_TYPE(static_cast<xcb_generic_event_t *>(message));
    if (responseType == damageExt_->first_event + XCB_DAMAGE_NOTIFY) {
        auto e = static_cast<xcb_damage_notify_event_t *>(message);
        auto i = pixmaps_.constFind(e->damage);
        if (i == pixmaps_.constEnd()) {
            return false;
        }
        (*i)->xcbEvent(e);
        return true;
    }

    switch (responseType) {
    case XCB_CREATE_NOTIFY:
        return xcbEvent(static_cast<xcb_create_notify_event_t *>(message));
    case XCB_DESTROY_NOTIFY:
        return xcbEvent(static_cast<xcb_destroy_notify_event_t *>(message));
    case XCB_REPARENT_NOTIFY:
        return xcbEvent(static_cast<xcb_reparent_notify_event_t *>(message));
    case XCB_CONFIGURE_NOTIFY:
        return xcbEvent(static_cast<xcb_configure_notify_event_t *>(message));
    case XCB_MAP_NOTIFY:
        return xcbEvent(static_cast<xcb_map_notify_event_t *>(message));
    case XCB_UNMAP_NOTIFY:
        return xcbEvent(static_cast<xcb_unmap_notify_event_t *>(message));
    case XCB_GRAVITY_NOTIFY:
        return xcbEvent(static_cast<xcb_gravity_notify_event_t *>(message));
    case XCB_CIRCULATE_NOTIFY:
        return xcbEvent(static_cast<xcb_circulate_notify_event_t *>(message));
    case XCB_PROPERTY_NOTIFY:
        return xcbEvent(static_cast<xcb_property_notify_event_t *>(message));
    default:
        return false;
    }
}
Ejemplo n.º 10
0
/* Handle a single event executing the handlers within its queue.
 * Prints an event dumb in case of empty queue. */
static void _handle(xcb_generic_event_t *e) {
    uint8_t sendEvent;
    uint16_t seq_num;
    fwm_eq_node_t *next_node;
    uint8_t response_type;
    fwm_eq_head_t *head;
    xcb_generic_error_t *er;

    /* Iterate queued handlers, if any. */
    response_type = XCB_EVENT_RESPONSE_TYPE(e);
    if (response_type) {
        head = _this.evenths_queue[response_type - 2];
        if (head != NULL) {
            next_node = head->first;
            while (next_node != NULL) {
                ((fwm_event_handler_t) (next_node->handler))(e);
                next_node = next_node->next;
            }
        }
    } else {
        /* Or format event if not to be handled. */
        sendEvent = response_type ? 1 : 0;
        seq_num = *((uint16_t *) e + 1);
        switch (response_type) {
            case 0:
                er = (xcb_generic_error_t *) e;
                printf("Error (%s) on sequence number %d.\n",
                        xcb_event_get_error_label(er->error_code), seq_num);
                break;
            default:
                printf("Unhandler event (%s) following seqnum %d.\n",
                        xcb_event_get_label(response_type), seq_num);
                break;
        }
        fflush(stdout);
    }
}
static void process_events(xcb_connection_t *c,
			   xcb_gcontext_t g,
			   xcb_window_t w,
			   xcb_pixmap_t p,
			   uint32_t width,
			   uint32_t height) {
    xcb_generic_event_t *e;
    xcb_void_cookie_t cookie;

    while ((e = xcb_wait_for_event(c))) {
	uint32_t r = XCB_EVENT_RESPONSE_TYPE(e);
	xcb_generic_error_t *err;
	
	fprintf(stderr, "event %d\n", r);
	switch (r) {
	case XCB_EXPOSE:
	case XCB_MAP_NOTIFY:
	    cookie = xcb_copy_area_checked(c, p, w, g,
					   0, 0, 0, 0,
					   width, height);
	    assert(!xcb_request_check(c, cookie));
	    break;
	case XCB_BUTTON_PRESS:
	    exit(0);
	    break;
	case 0:
	    err = (xcb_generic_error_t *) e;
	    printf("error: %d (sequence %d)\n",
		   err->error_code, (unsigned int) err->full_sequence);
	    exit(1);
	default:
	    break;
	}
	free(e);
    }
}
Ejemplo n.º 12
0
/** Emit a button signal.
 * The top of the lua stack has to be the object on which to emit the event.
 * \param L The Lua VM state.
 * \param ev The event to handle.
 */
static void
event_emit_button(lua_State *L, xcb_button_press_event_t *ev)
{
    const char *name;
    switch(XCB_EVENT_RESPONSE_TYPE(ev))
    {
    case XCB_BUTTON_PRESS:
        name = "button::press";
        break;
    case XCB_BUTTON_RELEASE:
        name = "button::release";
        break;
    default:
        fatal("Invalid event type");
    }

    /* Push the event's info */
    lua_pushinteger(L, ev->event_x);
    lua_pushinteger(L, ev->event_y);
    lua_pushinteger(L, ev->detail);
    luaA_pushmodifiers(L, ev->state);
    /* And emit the signal */
    luaA_object_emit_signal(L, -5, name, 4);
}
Ejemplo n.º 13
0
void track_pointer(coordinates_t loc, pointer_action_t pac, xcb_point_t pos)
{
	node_t *n = loc.node;
	resize_handle_t rh = get_handle(loc.node, pos, pac);

	uint16_t last_motion_x = pos.x, last_motion_y = pos.y;
	xcb_timestamp_t last_motion_time = 0;

	xcb_generic_event_t *evt = NULL;

	grabbing = true;
	grabbed_node = n;

	do {
		free(evt);
		while ((evt = xcb_wait_for_event(dpy)) == NULL) {
			xcb_flush(dpy);
		}
		uint8_t resp_type = XCB_EVENT_RESPONSE_TYPE(evt);
		if (resp_type == XCB_MOTION_NOTIFY) {
			xcb_motion_notify_event_t *e = (xcb_motion_notify_event_t*) evt;
			uint32_t dtime = e->time - last_motion_time;
			if (dtime < pointer_motion_interval) {
				continue;
			}
			last_motion_time = e->time;
			int16_t dx = e->root_x - last_motion_x;
			int16_t dy = e->root_y - last_motion_y;
			if (pac == ACTION_MOVE) {
				move_client(&loc, dx, dy);
			} else {
				resize_client(&loc, rh, e->root_x, e->root_y, false);
			}
			last_motion_x = e->root_x;
			last_motion_y = e->root_y;
			xcb_flush(dpy);
		} else if (resp_type == XCB_BUTTON_RELEASE) {
			grabbing = false;
		} else {
			handle_event(evt);
		}
	} while (grabbing && grabbed_node != NULL);
	free(evt);

	xcb_ungrab_pointer(dpy, XCB_CURRENT_TIME);

	if (grabbed_node == NULL) {
		grabbing = false;
		return;
	}

	if (pac == ACTION_MOVE) {
		put_status(SBSC_MASK_POINTER_ACTION, "pointer_action 0x%08X 0x%08X 0x%08X move end\n", loc.monitor->id, loc.desktop->id, n->id);
	} else if (pac == ACTION_RESIZE_CORNER) {
		put_status(SBSC_MASK_POINTER_ACTION, "pointer_action 0x%08X 0x%08X 0x%08X resize_corner end\n", loc.monitor->id, loc.desktop->id, n->id);
	} else if (pac == ACTION_RESIZE_SIDE) {
		put_status(SBSC_MASK_POINTER_ACTION, "pointer_action 0x%08X 0x%08X 0x%08X resize_side end\n", loc.monitor->id, loc.desktop->id, n->id);
	}

	xcb_rectangle_t r = get_rectangle(NULL, NULL, n);

	put_status(SBSC_MASK_NODE_GEOMETRY, "node_geometry 0x%08X 0x%08X 0x%08X %ux%u+%i+%i\n", loc.monitor->id, loc.desktop->id, loc.node->id, r.width, r.height, r.x, r.y);

	if ((pac == ACTION_MOVE && IS_TILED(n->client)) ||
	    ((pac == ACTION_RESIZE_CORNER || pac == ACTION_RESIZE_SIDE) &&
	     n->client->state == STATE_TILED)) {
		for (node_t *f = first_extrema(loc.desktop->root); f != NULL; f = next_leaf(f, loc.desktop->root)) {
			if (f == n || f->client == NULL || !IS_TILED(f->client)) {
				continue;
			}
			xcb_rectangle_t r = f->client->tiled_rectangle;
			put_status(SBSC_MASK_NODE_GEOMETRY, "node_geometry 0x%08X 0x%08X 0x%08X %ux%u+%i+%i\n", loc.monitor->id, loc.desktop->id, f->id, r.width, r.height, r.x, r.y);
		}
	}
}
Ejemplo n.º 14
0
void
xpost_view_main_loop(const Xpost_View_Window *win)
{
    xcb_intern_atom_cookie_t cookie1;
    xcb_intern_atom_cookie_t cookie2;
    xcb_intern_atom_reply_t* reply1;
    xcb_intern_atom_reply_t* reply2;
    int finished;

    /*
     * Listen to X client messages in order to be able to pickup
     * the "delete window" message that is generated for example
     * when someone clicks the top-right X button within the window
     * manager decoration (or when user hits ALT-F4).
     */
    cookie1 = xcb_intern_atom(win->c, 1,
                              sizeof("WM_DELETE_WINDOW") - 1, "WM_DELETE_WINDOW");
    cookie2 = xcb_intern_atom(win->c, 1,
                              sizeof("WM_PROTOCOLS") - 1, "WM_PROTOCOLS");
    reply1 = xcb_intern_atom_reply(win->c, cookie1, 0);
    reply2 = xcb_intern_atom_reply(win->c, cookie2, 0);
    xcb_change_property(win->c, XCB_PROP_MODE_REPLACE, win->window, reply2->atom, 4, 32, 1,
                        &reply1->atom);

    finished = 0;
    while (!finished)
    {
        xcb_generic_event_t *e;

        if ((e = xcb_poll_for_event(win->c)))
        {
            switch (XCB_EVENT_RESPONSE_TYPE(e))
            {
                case XCB_EXPOSE:
                    xcb_image_put(win->c, win->window, win->gc, win->image, 0, 0, 0);
                    xcb_flush(win->c);
                    break;
                case XCB_CLIENT_MESSAGE:
                {
                    xcb_client_message_event_t *event;

                    printf("client message\n");
                    event = (xcb_client_message_event_t *)e;
                    if (event->data.data32[0] == reply1->atom)
                        finished = 1;
                    break;
                }
                case XCB_BUTTON_PRESS:
                    printf("button pressed\n");
                    finished = 1;
                    break;
                case XCB_KEY_RELEASE:
                {
                    xcb_key_release_event_t *event;

                    event = (xcb_key_release_event_t *)e;
                    if (event->detail == 113)
                        xpost_view_page_change(-1);
                    if (event->detail == 114)
                        xpost_view_page_change(1);
                    break;
                }
            }
            free (e);
        }

        xcb_flush (win->c);
    }

    free(reply2);
    free(reply1);
}
Ejemplo n.º 15
0
void print_x_event(xcb_generic_event_t *event)
{
    uint8_t event_type = XCB_EVENT_RESPONSE_TYPE(event);
    const char *label = xcb_event_get_label(event_type);
    fprintf(stderr, "X event %d : %s\n", event_type, label);
}
Ejemplo n.º 16
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;
}
Ejemplo n.º 17
0
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;
}
Ejemplo n.º 18
0
/** The button press event handler.
 * \param ev The event.
 */
static void
event_handle_button(xcb_button_press_event_t *ev)
{
    lua_State *L = globalconf_get_lua_State();
    client_t *c;
    drawin_t *drawin;

    globalconf.timestamp = ev->time;

    {
        /* ev->state contains the state before the event. Compute the state
         * after the event for the mousegrabber.
         */
        uint16_t state = ev->state, change = 1 << (ev->detail - 1 + 8);
        if (XCB_EVENT_RESPONSE_TYPE(ev) == XCB_BUTTON_PRESS)
            state |= change;
        else
            state &= ~change;
        if(event_handle_mousegrabber(ev->root_x, ev->root_y, state))
            return;
    }

    /* 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((drawin = drawin_getbywin(ev->event))
       || (drawin = drawin_getbywin(ev->child)))
    {
        /* If the drawin is child, then x,y are
         * relative to root window */
        if(drawin->window == ev->child)
        {
            ev->event_x -= drawin->geometry.x + drawin->border_width;
            ev->event_y -= drawin->geometry.y + drawin->border_width;
        }

        /* Push the drawable */
        luaA_object_push(L, drawin);
        luaA_object_push_item(L, -1, drawin->drawable);
        /* and handle the button raw button event */
        event_emit_button(L, ev);
        lua_pop(L, 1);
        /* check if any button object matches */
        event_button_callback(ev, &drawin->buttons, L, -1, 1, NULL);
        /* Either we are receiving this due to ButtonPress/Release on the root
         * window or because we grabbed the button on the window. In the later
         * case we have to call AllowEvents.
         * Use AsyncPointer instead of ReplayPointer so that the event is
         * "eaten" instead of being handled again on the root window.
         */
        if(ev->child == XCB_NONE)
            xcb_allow_events(globalconf.connection,
                             XCB_ALLOW_ASYNC_POINTER,
                             ev->time);
    }
    else if((c = client_getbyframewin(ev->event)) || (c = client_getbywin(ev->event)))
    {
        /* For clicks inside of c->window, we get two events. Once because of a
         * passive grab on c->window and then again for c->frame_window.
         * Ignore the second event (identifiable by ev->child != XCB_NONE).
         */
        if (ev->event != c->frame_window || ev->child == XCB_NONE)
        {
            luaA_object_push(L, c);
            if (c->window == ev->event)
            {
                /* Button event into the client itself (not titlebar), translate
                 * into the frame window.
                 */
                ev->event_x += c->titlebar[CLIENT_TITLEBAR_LEFT].size;
                ev->event_y += c->titlebar[CLIENT_TITLEBAR_TOP].size;
            }
            /* And handle the button raw button event */
            event_emit_button(L, ev);
            /* then check if a titlebar was "hit" */
            if (c->frame_window == ev->event)
            {
                int x = ev->event_x, y = ev->event_y;
                drawable_t *d = client_get_drawable_offset(c, &x, &y);
                if (d)
                {
                    /* Copy the event so that we can fake x/y */
                    xcb_button_press_event_t event = *ev;
                    event.event_x = x;
                    event.event_y = y;
                    luaA_object_push_item(L, -1, d);
                    event_emit_button(L, &event);
                    lua_pop(L, 1);
                }
            }
            /* then check if any button objects match */
            event_button_callback(ev, &c->buttons, L, -1, 1, NULL);
        }
        xcb_allow_events(globalconf.connection,
                         XCB_ALLOW_REPLAY_POINTER,
                         ev->time);
    }
    else if(ev->child == XCB_NONE)
        if(globalconf.screen->root == ev->event)
        {
            event_button_callback(ev, &globalconf.buttons, L, 0, 0, NULL);
            return;
        }
}
Ejemplo n.º 19
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, 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;
}
Ejemplo n.º 20
0
void event_handle(xcb_generic_event_t *event)
{
    uint8_t response_type = XCB_EVENT_RESPONSE_TYPE(event);

    if(response_type == 0)
    {
        /* This is an error, not a event */
        xerror((xcb_generic_error_t *) event);
        return;
    }

    switch(response_type)
    {
#define EVENT(type, callback) case type: callback((void *) event); return
        EVENT(XCB_BUTTON_PRESS, event_handle_button);
        EVENT(XCB_BUTTON_RELEASE, event_handle_button);
        EVENT(XCB_CONFIGURE_REQUEST, event_handle_configurerequest);
        EVENT(XCB_CONFIGURE_NOTIFY, event_handle_configurenotify);
        EVENT(XCB_DESTROY_NOTIFY, event_handle_destroynotify);
        EVENT(XCB_ENTER_NOTIFY, event_handle_enternotify);
        EVENT(XCB_CLIENT_MESSAGE, event_handle_clientmessage);
        EVENT(XCB_EXPOSE, event_handle_expose);
        EVENT(XCB_FOCUS_IN, event_handle_focusin);
        EVENT(XCB_KEY_PRESS, event_handle_key);
        EVENT(XCB_KEY_RELEASE, event_handle_key);
        EVENT(XCB_LEAVE_NOTIFY, event_handle_leavenotify);
        EVENT(XCB_MAPPING_NOTIFY, event_handle_mappingnotify);
        EVENT(XCB_MAP_REQUEST, event_handle_maprequest);
        EVENT(XCB_MOTION_NOTIFY, event_handle_motionnotify);
        EVENT(XCB_PROPERTY_NOTIFY, property_handle_propertynotify);
        EVENT(XCB_REPARENT_NOTIFY, event_handle_reparentnotify);
        EVENT(XCB_UNMAP_NOTIFY, event_handle_unmapnotify);
        EVENT(XCB_SELECTION_CLEAR, event_handle_selectionclear);
#undef EVENT
    }

    static uint8_t randr_screen_change_notify = 0;
    static uint8_t randr_output_change_notify = 0;
    static uint8_t shape_notify = 0;
    static uint8_t xkb_notify = 0;

    if(randr_screen_change_notify == 0 || randr_output_change_notify == 0)
    {
        /* check for randr extension */
        const xcb_query_extension_reply_t *randr_query;
        randr_query = xcb_get_extension_data(globalconf.connection, &xcb_randr_id);
        if(randr_query->present) {
            xcb_randr_select_input(globalconf.connection, globalconf.screen->root, XCB_RANDR_NOTIFY_MASK_OUTPUT_CHANGE);
            randr_screen_change_notify = randr_query->first_event + XCB_RANDR_SCREEN_CHANGE_NOTIFY;
            randr_output_change_notify = randr_query->first_event + XCB_RANDR_NOTIFY;
        }
    }

    if(shape_notify == 0)
    {
        /* check for shape extension */
        const xcb_query_extension_reply_t *shape_query;
        shape_query = xcb_get_extension_data(globalconf.connection, &xcb_shape_id);
        if(shape_query->present)
            shape_notify = shape_query->first_event + XCB_SHAPE_NOTIFY;
    }

    if(xkb_notify == 0)
    {
        /* check for xkb extension */
        const xcb_query_extension_reply_t *xkb_query;
        xkb_query = xcb_get_extension_data(globalconf.connection, &xcb_xkb_id);
        if(xkb_query->present)
            xkb_notify = xkb_query->first_event;
    }

    if (response_type == randr_screen_change_notify)
        event_handle_randr_screen_change_notify((void *) event);
    if (response_type == randr_output_change_notify)
        event_handle_randr_output_change_notify((void *) event);
    if (response_type == shape_notify)
        event_handle_shape_notify((void *) event);
    if (response_type == xkb_notify)
        event_handle_xkb_notify((void *) event);
}
Ejemplo n.º 21
0
/** Get the current X selection buffer.
 * \param L The Lua VM state.
 * \return The number of elements pushed on stack.
 * \luastack
 * \lreturn A string with the current X selection buffer.
 */
int
luaA_selection_get(lua_State *L)
{
    if(selection_window == XCB_NONE)
    {
        xcb_screen_t *screen = xutil_screen_get(globalconf.connection, globalconf.default_screen);
        uint32_t mask = XCB_CW_BACK_PIXEL | XCB_CW_OVERRIDE_REDIRECT | XCB_CW_EVENT_MASK;
        uint32_t values[] = { screen->black_pixel, 1, XCB_EVENT_MASK_PROPERTY_CHANGE };

        selection_window = xcb_generate_id(globalconf.connection);

        xcb_create_window(globalconf.connection, screen->root_depth, selection_window, screen->root,
                          0, 0, 1, 1, 0, XCB_COPY_FROM_PARENT, screen->root_visual,
                          mask, values);
    }

    xcb_convert_selection(globalconf.connection, selection_window,
                          PRIMARY, UTF8_STRING, XSEL_DATA, XCB_CURRENT_TIME);
    xcb_flush(globalconf.connection);

    xcb_generic_event_t *event;

    while(true)
    {
        event = xcb_wait_for_event(globalconf.connection);

        if(!event)
            return 0;

        if(XCB_EVENT_RESPONSE_TYPE(event) != XCB_SELECTION_NOTIFY)
        {
            /* \todo Eventually, this may be rewritten with adding a static
             * buffer, then a event handler for XCB_SELECTION_NOTIFY, then call
             * xcb_event_poll_for_event_loop() and awesome_refresh(),
             * then check if some static buffer has been filled with data.
             * If yes, that'd be the xsel data, otherwise, re-loop.
             * Anyway that's still brokes the socket or D-Bus, so maybe using
             * ev_loop() would be even better.
             */
            xcb_event_handle(&globalconf.evenths, event);
            p_delete(&event);
            awesome_refresh();
            continue;
        }

        xcb_selection_notify_event_t *event_notify =
            (xcb_selection_notify_event_t *) event;

        if(event_notify->selection == PRIMARY
           && event_notify->property != XCB_NONE)
        {
            xcb_get_text_property_reply_t prop;
            xcb_get_property_cookie_t cookie =
                xcb_get_text_property(globalconf.connection,
                                      event_notify->requestor,
                                      event_notify->property);

            if(xcb_get_text_property_reply(globalconf.connection,
                                           cookie, &prop, NULL))
            {
                lua_pushlstring(L, prop.name, prop.name_len);

                xcb_get_text_property_reply_wipe(&prop);

                xcb_delete_property(globalconf.connection,
                                    event_notify->requestor,
                                    event_notify->property);

                p_delete(&event);

                return 1;
            }
            else
                break;
        }
    }

    p_delete(&event);
    return 0;
}
Ejemplo n.º 22
0
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);
}