Ejemplo n.º 1
0
	void
	Window::create_window(xcb_window_t parent, int32_t x, int32_t y, uint32_t w, uint32_t h)
	{
		window = xcb_generate_id(conn->xcb());
		
		const xcb_screen_t*	screen = conn->get_root();
		uint32_t		values[1] = {0};
		conn->check(xcb_create_window_checked(conn->xcb(), screen->root_depth, window, parent, x, y, w, h, 0, XCB_WINDOW_CLASS_INPUT_OUTPUT, screen->root_visual, 0, values));
	}
Ejemplo n.º 2
0
Archivo: nilwm.c Proyecto: nqv/nilwm
static
int init_bar() {
    uint32_t vals[4];
    xcb_void_cookie_t cookie;
    xcb_generic_error_t *err;

    /* create status bar window at the bottom */
    bar_.w = nil_.scr->width_in_pixels;
    bar_.h = nil_.font.ascent + nil_.font.descent + 2;
    bar_.x = 0;
    bar_.y = nil_.scr->height_in_pixels - bar_.h;
    bar_.win = xcb_generate_id(nil_.con);
    vals[0] = XCB_BACK_PIXMAP_PARENT_RELATIVE;
    vals[1] = 1;    /* override_redirect */
    vals[2] = XCB_EVENT_MASK_BUTTON_PRESS | XCB_EVENT_MASK_EXPOSURE;
    vals[3] = nil_.cursor[CURSOR_NORMAL];

    cookie = xcb_create_window_checked(nil_.con, nil_.scr->root_depth, bar_.win,
        nil_.scr->root, bar_.x, bar_.y, bar_.w, bar_.h, 0, XCB_COPY_FROM_PARENT,
        nil_.scr->root_visual, XCB_CW_BACK_PIXMAP | XCB_CW_OVERRIDE_REDIRECT
        | XCB_CW_EVENT_MASK | XCB_CW_CURSOR, vals);
    err = xcb_request_check(nil_.con, cookie);
    if (err) {
        NIL_ERR("create window %d", err->error_code);
        return -1;
    }
    vals[0] = XCB_STACK_MODE_ABOVE;
    xcb_configure_window(nil_.con, bar_.win, XCB_CONFIG_WINDOW_STACK_MODE, &vals[0]);
    cookie = xcb_map_window_checked(nil_.con, bar_.win);
    err = xcb_request_check(nil_.con, cookie);
    if (err) {
        NIL_ERR("map window %d", err->error_code);
        return -1;
    }
    /* graphic context */
    bar_.gc = xcb_generate_id(nil_.con);
    vals[0] = nil_.color.bar_fg;
    vals[1] = nil_.color.bar_bg;
    vals[2] = nil_.font.id;
    cookie = xcb_create_gc_checked(nil_.con, bar_.gc, bar_.win, XCB_GC_FOREGROUND
        | XCB_GC_BACKGROUND | XCB_GC_FONT, vals);
    err = xcb_request_check(nil_.con, cookie);
    if (err) {
        NIL_ERR("map window %d", err->error_code);
        return -1;
    }
    return 0;
}
Ejemplo n.º 3
0
void shutdown_init() {

	xcb_void_cookie_t void_cookie;

	shutdown_win.surface=NULL;
	
	shutdown_win.window = xcb_generate_id(conn);
	uint32_t values[1] = {XCB_EVENT_MASK_EXPOSURE|XCB_EVENT_MASK_BUTTON_RELEASE};

	void_cookie=xcb_create_window_checked (conn,XCB_COPY_FROM_PARENT,shutdown_win.window,scr->root,0,height-1,width,1,0,XCB_WINDOW_CLASS_INPUT_OUTPUT,scr->root_visual,XCB_CW_EVENT_MASK,values);

	xcb_flush(conn);

	if (xcb_request_check(conn,void_cookie)) {
		printf("Can't create the shutdown window\n");
		shutdown_win.window = 0;
	} else {
		uint32_t v[4];
		uint32_t value_mask;

		value_mask=XCB_CONFIG_WINDOW_X|XCB_CONFIG_WINDOW_Y|XCB_CONFIG_WINDOW_WIDTH|XCB_CONFIG_WINDOW_HEIGHT;
		v[0]=width/4;;
		v[1]=height/4;
		v[2]=width/2;
		v[3]=height/2;
		shutdown_win.width=v[2];
		shutdown_win.height=v[3];
		xcb_configure_window(conn,shutdown_win.window,value_mask,v);
		xcb_change_property(conn,XCB_PROP_MODE_REPLACE,shutdown_win.window,atoms[TWM_ATOM__NET_WM_NAME],XCB_ATOM_STRING,8,strlen(TWM_NAME),TWM_NAME);
		xcb_change_property(conn,XCB_PROP_MODE_REPLACE,shutdown_win.window,atoms[TWM_ATOM__NET_WM_WINDOW_TYPE],XCB_ATOM_ATOM,32,1,&atoms[TWM_ATOM__NET_WM_WINDOW_TYPE_DOCK]);
		shutdown_win.cache=wincache_fill_element(shutdown_win.window);
		shutdown_win.cache->mapped=0;
		xcb_flush(conn);
		shutdown_win.surface=cairo_xcb_surface_create(conn,shutdown_win.window,visual_type,width/2,height/2);
		cairo_xcb_surface_set_size(shutdown_win.surface,v[2],v[3]);
		xcb_flush(conn);
	}
}
Ejemplo n.º 4
0
void init_tabletwm() {

	memset(&key_win, 0, sizeof(key_win));
	memset(&shutdown_win, 0, sizeof(shutdown_win));
	xcb_void_cookie_t void_cookie;
	xcb_intern_atom_cookie_t atom_cookie[TWM_ATOM_LAST_VALUE];
	uint32_t v[] = {XCB_EVENT_MASK_SUBSTRUCTURE_NOTIFY | XCB_EVENT_MASK_SUBSTRUCTURE_REDIRECT | XCB_EVENT_MASK_PROPERTY_CHANGE};
	int i;

	char *a_atoms[TWM_ATOM_LAST_VALUE] = {
		"WM_SIZE_HINTS",
		"WM_NORMAL_HINTS",
		"WM_PROTOCOLS",
		"WM_DELETE_WINDOW",
		"WM_TRANSIENT_FOR",
		"_NET_SUPPORTING_WM_CHECK",
		"_NET_WM_NAME",
		"_NET_SUPPORTED",

		"_NET_WM_WINDOW_TYPE",
		"_NET_WM_WINDOW_TYPE_DESKTOP",
		"_NET_WM_WINDOW_TYPE_DOCK",
		"_NET_WM_WINDOW_TYPE_TOOLBAR",
		"_NET_WM_WINDOW_TYPE_MENU",
		"_NET_WM_WINDOW_TYPE_UTILITY",
		"_NET_WM_WINDOW_TYPE_SPLASH",
		"_NET_WM_WINDOW_TYPE_DIALOG",
		"_NET_WM_WINDOW_TYPE_DROPDOWN_MENU",
		"_NET_WM_WINDOW_TYPE_POPUP_MENU",
		"_NET_WM_WINDOW_TYPE_TOOLTIP",
		"_NET_WM_WINDOW_TYPE_NOTIFICATION",
		"_NET_WM_WINDOW_TYPE_COMBO",
		"_NET_WM_WINDOW_TYPE_DND",
		"_NET_WM_WINDOW_TYPE_NORMAL",

		"_NET_WM_ALLOWED_ACTIONS",
		"_NET_WM_ACTION_MOVE",
		"_NET_WM_ACTION_RESIZE",
		"_NET_WM_ACTION_MINIMIZE",
		"_NET_WM_ACTION_SHADE",
		"_NET_WM_ACTION_STICK",
		"_NET_WM_ACTION_MAXIMIZE_HORZ",
		"_NET_WM_ACTION_MAXIMIZE_VERT",
		"_NET_WM_ACTION_FULLSCREEN",
		"_NET_WM_ACTION_CHANGE_DESKTOP",
		"_NET_WM_ACTION_CLOSE",
		"_NET_WM_ACTION_ABOVE",
		"_NET_WM_ACTION_BELOW",

		"WM_CLASS",
		"WM_STATE",
		"_NET_ACTIVE_WINDOW",
		"WM_HINTS",
		"_XKB_RULES_NAMES",
	};

	init_load_config();

	wincache_init();

	conn = xcb_connect(0, 0);
	assert(conn);

	scr = xcb_setup_roots_iterator(xcb_get_setup(conn)).data;
	width = scr->width_in_pixels;
	height = scr->height_in_pixels; // reserve the bottom part for the 1pixel-height, collapsed menu bar

	xcb_change_window_attributes(conn, scr->root, XCB_CW_EVENT_MASK, v);

	xcb_depth_iterator_t depth_iter;
	xcb_visualid_t root_visual = { 0 };
	visual_type = NULL;

	for (depth_iter = xcb_screen_allowed_depths_iterator (scr); depth_iter.rem; xcb_depth_next (&depth_iter)) {
		xcb_visualtype_iterator_t visual_iter;

		visual_iter = xcb_depth_visuals_iterator (depth_iter.data);
		for (; visual_iter.rem; xcb_visualtype_next (&visual_iter)) {
			if (scr->root_visual == visual_iter.data->visual_id) {
				visual_type = visual_iter.data;
				break;
			}
		}
	}

	/* get atoms */
	for(i=0; i < TWM_ATOM_LAST_VALUE; i++) {
		atom_cookie[i] = xcb_intern_atom_unchecked(conn, 0, strlen(a_atoms[i]), a_atoms[i]);
	};

	xcb_flush(conn);

	xcb_intern_atom_reply_t *atom_reply;
	for(i=0; i < TWM_ATOM_LAST_VALUE; i++) {
		atom_reply = xcb_intern_atom_reply(conn, atom_cookie[i], 0),
		atoms[i] = atom_reply->atom;
		free(atom_reply);
	};

	xcb_change_property(conn, XCB_PROP_MODE_REPLACE, scr->root, atoms[TWM_ATOM__NET_SUPPORTED], XCB_ATOM_ATOM, 32, 1, &atoms[TWM_ATOM_WM_DELETE_WINDOW]);
	xcb_change_property(conn, XCB_PROP_MODE_APPEND, scr->root, atoms[TWM_ATOM__NET_SUPPORTED], XCB_ATOM_ATOM, 32, 1, &atoms[TWM_ATOM__NET_WM_WINDOW_TYPE]);
	xcb_change_property(conn, XCB_PROP_MODE_APPEND, scr->root, atoms[TWM_ATOM__NET_SUPPORTED], XCB_ATOM_ATOM, 32, 1, &atoms[TWM_ATOM__NET_WM_WINDOW_TYPE_DESKTOP]);
	xcb_change_property(conn, XCB_PROP_MODE_APPEND, scr->root, atoms[TWM_ATOM__NET_SUPPORTED], XCB_ATOM_ATOM, 32, 1, &atoms[TWM_ATOM__NET_WM_WINDOW_TYPE_DOCK]);
	xcb_change_property(conn, XCB_PROP_MODE_APPEND, scr->root, atoms[TWM_ATOM__NET_SUPPORTED], XCB_ATOM_ATOM, 32, 1, &atoms[TWM_ATOM__NET_WM_WINDOW_TYPE_TOOLBAR]);
	xcb_change_property(conn, XCB_PROP_MODE_APPEND, scr->root, atoms[TWM_ATOM__NET_SUPPORTED], XCB_ATOM_ATOM, 32, 1, &atoms[TWM_ATOM__NET_WM_WINDOW_TYPE_MENU]);
	xcb_change_property(conn, XCB_PROP_MODE_APPEND, scr->root, atoms[TWM_ATOM__NET_SUPPORTED] , XCB_ATOM_ATOM, 32, 1, &atoms[TWM_ATOM__NET_WM_WINDOW_TYPE_UTILITY]);
	xcb_change_property(conn, XCB_PROP_MODE_APPEND, scr->root, atoms[TWM_ATOM__NET_SUPPORTED], XCB_ATOM_ATOM, 32, 1, &atoms[TWM_ATOM__NET_WM_WINDOW_TYPE_SPLASH]);
	xcb_change_property(conn, XCB_PROP_MODE_APPEND, scr->root, atoms[TWM_ATOM__NET_SUPPORTED], XCB_ATOM_ATOM, 32, 1, &atoms[TWM_ATOM__NET_WM_WINDOW_TYPE_DIALOG]);
	xcb_change_property(conn, XCB_PROP_MODE_APPEND, scr->root, atoms[TWM_ATOM__NET_SUPPORTED], XCB_ATOM_ATOM, 32, 1, &atoms[TWM_ATOM__NET_WM_WINDOW_TYPE_DROPDOWN_MENU]);
	xcb_change_property(conn, XCB_PROP_MODE_APPEND, scr->root, atoms[TWM_ATOM__NET_SUPPORTED], XCB_ATOM_ATOM, 32, 1, &atoms[TWM_ATOM__NET_WM_WINDOW_TYPE_POPUP_MENU]);
	xcb_change_property(conn, XCB_PROP_MODE_APPEND, scr->root, atoms[TWM_ATOM__NET_SUPPORTED], XCB_ATOM_ATOM, 32, 1, &atoms[TWM_ATOM__NET_WM_WINDOW_TYPE_TOOLTIP]);
	xcb_change_property(conn, XCB_PROP_MODE_APPEND, scr->root, atoms[TWM_ATOM__NET_SUPPORTED], XCB_ATOM_ATOM, 32, 1, &atoms[TWM_ATOM__NET_WM_WINDOW_TYPE_NOTIFICATION]);
	xcb_change_property(conn, XCB_PROP_MODE_APPEND, scr->root, atoms[TWM_ATOM__NET_SUPPORTED], XCB_ATOM_ATOM, 32, 1, &atoms[TWM_ATOM__NET_WM_WINDOW_TYPE_COMBO]);
	xcb_change_property(conn, XCB_PROP_MODE_APPEND, scr->root, atoms[TWM_ATOM__NET_SUPPORTED], XCB_ATOM_ATOM, 32, 1, &atoms[TWM_ATOM__NET_WM_WINDOW_TYPE_DND]);
	xcb_change_property(conn, XCB_PROP_MODE_APPEND, scr->root, atoms[TWM_ATOM__NET_SUPPORTED], XCB_ATOM_ATOM, 32, 1, &atoms[TWM_ATOM__NET_WM_WINDOW_TYPE_NORMAL]);

	xcb_change_property(conn, XCB_PROP_MODE_APPEND, scr->root, atoms[TWM_ATOM__NET_SUPPORTED], XCB_ATOM_ATOM, 32, 1, &atoms[TWM_ATOM__NET_WM_ALLOWED_ACTIONS]);
	xcb_change_property(conn, XCB_PROP_MODE_APPEND, scr->root, atoms[TWM_ATOM__NET_SUPPORTED], XCB_ATOM_ATOM, 32, 1, &atoms[TWM_ATOM__NET_WM_ACTION_MOVE]);
	xcb_change_property(conn, XCB_PROP_MODE_APPEND, scr->root, atoms[TWM_ATOM__NET_SUPPORTED], XCB_ATOM_ATOM, 32, 1, &atoms[TWM_ATOM__NET_WM_ACTION_RESIZE]);
	xcb_change_property(conn, XCB_PROP_MODE_APPEND, scr->root, atoms[TWM_ATOM__NET_SUPPORTED], XCB_ATOM_ATOM, 32, 1, &atoms[TWM_ATOM__NET_WM_ACTION_MINIMIZE]);
	xcb_change_property(conn, XCB_PROP_MODE_APPEND, scr->root, atoms[TWM_ATOM__NET_SUPPORTED], XCB_ATOM_ATOM, 32, 1, &atoms[TWM_ATOM__NET_WM_ACTION_SHADE]);
	xcb_change_property(conn, XCB_PROP_MODE_APPEND, scr->root, atoms[TWM_ATOM__NET_SUPPORTED], XCB_ATOM_ATOM, 32, 1, &atoms[TWM_ATOM__NET_WM_ACTION_STICK]);
	xcb_change_property(conn, XCB_PROP_MODE_APPEND, scr->root, atoms[TWM_ATOM__NET_SUPPORTED], XCB_ATOM_ATOM, 32, 1, &atoms[TWM_ATOM__NET_WM_ACTION_MAXIMIZE_HORZ]);
	xcb_change_property(conn, XCB_PROP_MODE_APPEND, scr->root, atoms[TWM_ATOM__NET_SUPPORTED], XCB_ATOM_ATOM, 32, 1, &atoms[TWM_ATOM__NET_WM_ACTION_MAXIMIZE_VERT]);
	xcb_change_property(conn, XCB_PROP_MODE_APPEND, scr->root, atoms[TWM_ATOM__NET_SUPPORTED], XCB_ATOM_ATOM, 32, 1, &atoms[TWM_ATOM__NET_WM_ACTION_FULLSCREEN]);
	xcb_change_property(conn, XCB_PROP_MODE_APPEND, scr->root, atoms[TWM_ATOM__NET_SUPPORTED], XCB_ATOM_ATOM, 32, 1, &atoms[TWM_ATOM__NET_WM_ACTION_CHANGE_DESKTOP]);
	xcb_change_property(conn, XCB_PROP_MODE_APPEND, scr->root, atoms[TWM_ATOM__NET_SUPPORTED], XCB_ATOM_ATOM, 32, 1, &atoms[TWM_ATOM__NET_WM_ACTION_CLOSE]);
	xcb_change_property(conn, XCB_PROP_MODE_APPEND, scr->root, atoms[TWM_ATOM__NET_SUPPORTED], XCB_ATOM_ATOM, 32, 1, &atoms[TWM_ATOM__NET_WM_ACTION_ABOVE]);
	xcb_change_property(conn, XCB_PROP_MODE_APPEND, scr->root, atoms[TWM_ATOM__NET_SUPPORTED], XCB_ATOM_ATOM, 32, 1, &atoms[TWM_ATOM__NET_WM_ACTION_BELOW]);

	// This window contains the menu and the virtual keyboard (when showed)
	// It is also used to ensure that the window manager is recognized as an Extended Window Manager Hints WM
	// By default it occupies one pixel at the bottom of the screen, to allow to detect when the mouse is moved to the bottom

	xcb_get_property_cookie_t kbd_info_cookie;
	xcb_get_property_reply_t *kbd_info;
	kbd_info_cookie = xcb_get_property(conn, 0, scr->root, atoms[TWM__XKB_RULES_NAMES], XCB_ATOM_STRING, 0, 1024);

	key_win.window = xcb_generate_id(conn);
	uint32_t values[1] = {XCB_EVENT_MASK_EXPOSURE|XCB_EVENT_MASK_BUTTON_RELEASE|XCB_EVENT_MASK_BUTTON_PRESS|XCB_EVENT_MASK_ENTER_WINDOW|XCB_EVENT_MASK_LEAVE_WINDOW};
	void_cookie=xcb_create_window_checked (conn, XCB_COPY_FROM_PARENT, key_win.window, scr->root, 0, height-1, width, 1, 0, XCB_WINDOW_CLASS_INPUT_OUTPUT, scr->root_visual, XCB_CW_EVENT_MASK, values);

	xcb_flush(conn);

	kbd_info = xcb_get_property_reply(conn, kbd_info_cookie, 0);
	if (kbd_info!=NULL) {
		if (kbd_info->length>0) {
			char *p=((char *)(xcb_get_property_value(kbd_info)));
			int counter=0;
			int len, max;
			max=xcb_get_property_value_length(kbd_info);
			char *end=p+max;
			do {
				len = strnlen(p, max);
				if (*p!=0) {
					xkb_names[counter++] = strdup(p);
				}
				p+=len+1;
				max-=len+1;
			} while ((p < end) && (counter < 5));
		}
		free(kbd_info);
	}

	if (xcb_request_check(conn, void_cookie)) {
		printf("Can't create the fake window\n");
	} else {
		menuwin_init();
	}
	shutdown_init();
}
Ejemplo n.º 5
0
//appContext
X11AppContext::X11AppContext()
{
    //XInitThreads(); //todo, make this optional
	impl_ = std::make_unique<Impl>();

    xDisplay_ = ::XOpenDisplay(nullptr);
    if(!xDisplay_)
        throw std::runtime_error("ny::X11AppContext: could not connect to X Server");

    xDefaultScreenNumber_ = ::XDefaultScreen(xDisplay_);

 	xConnection_ = ::XGetXCBConnection(xDisplay_);
    if(!xConnection_ || xcb_connection_has_error(xConnection_))
		throw std::runtime_error("ny::X11AppContext: unable to get xcb connection");

	impl_->errorCategory = {*xDisplay_, *xConnection_};
	auto ewmhCookie = xcb_ewmh_init_atoms(&xConnection(), &ewmhConnection());

	//query information
	auto iter = xcb_setup_roots_iterator(xcb_get_setup(&xConnection()));
	for(auto i = 0; iter.rem; ++i, xcb_screen_next(&iter))
	{
	    if(i == xDefaultScreenNumber_)
		{
			xDefaultScreen_ = iter.data;
			break;
	    }
	}

	//This must be called because xcb is used to access the event queue
    ::XSetEventQueueOwner(xDisplay_, XCBOwnsEventQueue);

	//Generate an x dummy window that can e.g. be used for selections
	//This window remains invisible, i.e. it is not begin mapped
	xDummyWindow_ = xcb_generate_id(xConnection_);
    auto cookie = xcb_create_window_checked(xConnection_, XCB_COPY_FROM_PARENT, xDummyWindow_,
		xDefaultScreen_->root, 0, 0, 50, 50, 0, XCB_WINDOW_CLASS_INPUT_ONLY,
		XCB_COPY_FROM_PARENT, 0, nullptr);
	errorCategory().checkThrow(cookie, "ny::X11AppContext: create_window for dummy window failed");

	//Load all default required atoms
	auto& atoms = impl_->atoms;
	struct
	{
		xcb_atom_t& atom;
		const char* name;
	} atomNames[] =
	{
		{atoms.xdndEnter, "XdndEnter"},
		{atoms.xdndPosition, "XdndPosition"},
		{atoms.xdndStatus, "XdndStatus"},
		{atoms.xdndTypeList, "XdndTypeList"},
		{atoms.xdndActionCopy, "XdndActionCopy"},
		{atoms.xdndActionMove, "XdndActionMove"},
		{atoms.xdndActionAsk, "XdndActionAsk"},
		{atoms.xdndDrop, "XdndDrop"},
		{atoms.xdndLeave, "XdndLeave"},
		{atoms.xdndFinished, "XdndFinished"},
		{atoms.xdndSelection, "XdndSelection"},
		{atoms.xdndProxy, "XdndProxy"},
		{atoms.xdndAware, "XdndAware"},

		{atoms.clipboard, "CLIPBOARD"},
		{atoms.targets, "TARGETS"},
		{atoms.text, "TEXT"},
		{atoms.utf8string, "UTF8_STRING"},
		{atoms.fileName, "FILE_NAME"},

		{atoms.wmDeleteWindow, "WM_DELETE_WINDOW"},
		{atoms.motifWmHints, "_MOTIF_WM_HINTS"},

		{atoms.mime.textPlain, "text/plain"},
		{atoms.mime.textPlainUtf8, "text/plain;charset=utf8"},
		{atoms.mime.textUriList, "text/uri-list"},

		{atoms.mime.imageJpeg, "image/jpeg"},
		{atoms.mime.imageGif, "image/gif"},
		{atoms.mime.imagePng, "image/png"},
		{atoms.mime.imageBmp, "image/bmp"},

		{atoms.mime.imageData, "image/x-ny-data"},
		{atoms.mime.timePoint, "x-application/ny-time-point"},
		{atoms.mime.timeDuration, "x-application/ny-time-duration"},
		{atoms.mime.raw, "x-application/ny-raw-buffer"},
	};

	auto length = sizeof(atomNames) / sizeof(atomNames[0]);

	std::vector<xcb_intern_atom_cookie_t> atomCookies;
	atomCookies.reserve(length);

	for(auto& name : atomNames)
		atomCookies.push_back(xcb_intern_atom(xConnection_, 0, std::strlen(name.name), name.name));

	for(auto i = 0u; i < atomCookies.size(); ++i)
	{
		xcb_generic_error_t* error {};
		auto reply = xcb_intern_atom_reply(xConnection_, atomCookies[i], &error);
		if(reply)
		{
			atomNames[i].atom = reply->atom;
			free(reply);
			continue;
		}
		else if(error)
		{
			auto msg = x11::errorMessage(xDisplay(), error->error_code);
			free(error);
			warning("ny::X11AppContext: Failed to load atom ", atomNames[i].name, ": ", msg);
		}
	}

	//ewmh
	xcb_ewmh_init_atoms_replies(&ewmhConnection(), ewmhCookie, nullptr);

	//input
	keyboardContext_ = std::make_unique<X11KeyboardContext>(*this);
	mouseContext_ = std::make_unique<X11MouseContext>(*this);
}
Ejemplo n.º 6
0
/* @brief The main function. Initialization happens here.
 *
 * @return 0 on success and 1 on failure.
 */
int main(int argc, char **argv) {
  int32_t exit_code = 0;
  atexit(kill_zombie);

  int c;
  char *config_file = CONFIG_FILE;
  while ((c = getopt(argc, argv, "c:")) != -1) {
    switch (c) {
      case 'c':
        config_file = optarg;
        break;
      default:
        break;
    }
  }

  if (initialize_settings(config_file)) {
    return 1;
  }

  int i;
  enum { MAX_ARGS = 64 };
  int nargs = 0;
  char *cmdargs[MAX_ARGS];

  /* one extra for the NULL */
  nargs = (argc - optind) + 2;
  if (nargs > 63)
    nargs = 63;

  for (i=optind; i < argc; i++) {
    if ((i - optind) + 1 > 62)
      break;
    cmdargs[(i - optind) + 1] = strdup(argv[i]);
  }

  cmdargs[nargs - 1] = NULL;

  /* Set up the remote process. */
  int32_t to_child_fd, from_child_fd;

  char *exec_file = settings.cmd;

  if (spawn_piped_process(exec_file, &to_child_fd, &from_child_fd, (char **)cmdargs)) {
    fprintf(stderr, "Failed to spawn piped process.\n");
    exit_code = 1;
    return exit_code;
  }

  /* Don't free #0, it is filled in by spawn_piped_process() and isn't memory that we own */
  for (i=1; i < nargs - 1 ; i++)
    free(cmdargs[i]);

  /* The main way to communicate with our remote process. */ 
  FILE *to_child = fdopen(to_child_fd, "w");

  /* Connect to the X server. */
  xcb_connection_t *connection = xcb_connect(NULL, NULL);

  /* Setup keyboard stuff. Thanks Apple! */
  xcb_key_symbols_t *keysyms = xcb_key_symbols_alloc(connection);

  /* Get the first screen. */
  const xcb_setup_t *setup = xcb_get_setup(connection);
  xcb_screen_iterator_t iter = xcb_setup_roots_iterator(setup);
  xcb_screen_t *screen = iter.data;

  /* Create a window. */
  xcb_window_t window = xcb_generate_id(connection);
  uint32_t values[2];
  values[0] = screen->white_pixel;
  values[1] = XCB_EVENT_MASK_EXPOSURE
            | XCB_EVENT_MASK_KEY_PRESS
            | XCB_EVENT_MASK_KEY_RELEASE
            | XCB_EVENT_MASK_BUTTON_PRESS;
  xcb_void_cookie_t window_cookie = xcb_create_window_checked(connection,
    XCB_COPY_FROM_PARENT, window, screen->root, 0, 0, settings.width, settings.height, 0,
    XCB_WINDOW_CLASS_INPUT_OUTPUT, screen->root_visual,
    XCB_CW_BACK_PIXEL | XCB_CW_EVENT_MASK, values);

  if (check_xcb_cookie(window_cookie, connection, "Failed to initialize window.")) {
    exit_code = 1;
    goto cleanup;
  }

  /* Get the atoms to create a dock window type. */
  xcb_atom_t window_type_atom, window_type_dock_atom;
  xcb_intern_atom_cookie_t atom_cookie = xcb_intern_atom(connection, 0, strlen("_NET_WM_WINDOW_TYPE"), "_NET_WM_WINDOW_TYPE");
  xcb_intern_atom_reply_t *atom_reply = xcb_intern_atom_reply(connection, atom_cookie, NULL); 
  if (!atom_reply) {
    fprintf(stderr, "Unable to set window type. You will need to manually set your window manager to run lighthouse as you'd like.\n");
  } else {
    window_type_atom = atom_reply->atom;
    free(atom_reply);

    atom_cookie = xcb_intern_atom(connection, 0, strlen("_NET_WM_WINDOW_TYPE_DOCK"), "_NET_WM_WINDOW_TYPE_DOCK");
    atom_reply = xcb_intern_atom_reply(connection, atom_cookie, NULL);
    if (atom_reply) {
      window_type_dock_atom = atom_reply->atom;
      free(atom_reply);
      xcb_change_property_checked(connection, XCB_PROP_MODE_REPLACE, window, window_type_atom, XCB_ATOM_ATOM, 32, 1, &window_type_dock_atom);
    } else {
      fprintf(stderr, "Unable to set window type. You will need to manually set your window manager to run lighthouse as you'd like.\n");
    }
  }

  /* Now set which desktop to run on. */
  xcb_atom_t desktop_atom;
  atom_cookie = xcb_intern_atom(connection, 0, strlen("_NET_WM_DESKTOP"), "_NET_WM_DESKTOP");
  atom_reply = xcb_intern_atom_reply(connection, atom_cookie, NULL); 
  if (!atom_reply) {
    fprintf(stderr, "Unable to set a specific desktop to launch on.\n");
  } else {
    desktop_atom = atom_reply->atom;
    free(atom_reply);
    xcb_change_property_checked(connection, XCB_PROP_MODE_REPLACE, window, desktop_atom, XCB_ATOM_ATOM, 32, 1, (const uint32_t []){ settings.desktop });
  }
Ejemplo n.º 7
0
Archivo: x11.c Proyecto: Annovae/vlc
/**
 * Probe the X server.
 */
static int Open (vlc_object_t *obj)
{
    vout_display_t *vd = (vout_display_t *)obj;
    vout_display_sys_t *sys = malloc (sizeof (*sys));
    if (unlikely(sys == NULL))
        return VLC_ENOMEM;

    vd->sys = sys;
    sys->pool = NULL;

    /* Get window, connect to X server */
    xcb_connection_t *conn;
    const xcb_screen_t *scr;
    uint16_t width, height;
    sys->embed = XCB_parent_Create (vd, &conn, &scr, &width, &height);
    if (sys->embed == NULL)
    {
        free (sys);
        return VLC_EGENERIC;
    }
    sys->conn = conn;

    const xcb_setup_t *setup = xcb_get_setup (conn);

    /* Determine our pixel format */
    video_format_t fmt_pic;
    xcb_visualid_t vid;
    sys->depth = 0;

    for (const xcb_format_t *fmt = xcb_setup_pixmap_formats (setup),
             *end = fmt + xcb_setup_pixmap_formats_length (setup);
         fmt < end;
         fmt++)
    {
        if (fmt->depth <= sys->depth)
            continue; /* no better than earlier format */

        fmt_pic = vd->fmt;

        /* Check that the pixmap format is supported by VLC. */
        switch (fmt->depth)
        {
          case 32:
            if (fmt->bits_per_pixel != 32)
                continue;
            fmt_pic.i_chroma = VLC_CODEC_ARGB;
            break;
          case 24:
            if (fmt->bits_per_pixel == 32)
                fmt_pic.i_chroma = VLC_CODEC_RGB32;
            else if (fmt->bits_per_pixel == 24)
                fmt_pic.i_chroma = VLC_CODEC_RGB24;
            else
                continue;
            break;
          case 16:
            if (fmt->bits_per_pixel != 16)
                continue;
            fmt_pic.i_chroma = VLC_CODEC_RGB16;
            break;
          case 15:
            if (fmt->bits_per_pixel != 16)
                continue;
            fmt_pic.i_chroma = VLC_CODEC_RGB15;
            break;
          case 8:
            if (fmt->bits_per_pixel != 8)
                continue;
            fmt_pic.i_chroma = VLC_CODEC_RGB8;
            break;
          default:
            continue;
        }

        /* Byte sex is a non-issue for 8-bits. It can be worked around with
         * RGB masks for 24-bits. Too bad for 15-bits and 16-bits. */
        if (fmt->bits_per_pixel == 16 && setup->image_byte_order != ORDER)
            continue;

        /* Make sure the X server is sane */
        assert (fmt->bits_per_pixel > 0);
        if (unlikely(fmt->scanline_pad % fmt->bits_per_pixel))
            continue;

        /* Check that the selected screen supports this depth */
        const xcb_depth_t *d = FindDepth (scr, fmt->depth);
        if (d == NULL)
            continue;

        /* Find a visual type for the selected depth */
        const xcb_visualtype_t *vt = xcb_depth_visuals (d);

        /* First try True Color class */
        for (int i = xcb_depth_visuals_length (d); i > 0; i--)
        {
            if (vt->_class == XCB_VISUAL_CLASS_TRUE_COLOR)
            {
                fmt_pic.i_rmask = vt->red_mask;
                fmt_pic.i_gmask = vt->green_mask;
                fmt_pic.i_bmask = vt->blue_mask;
            found_visual:
                vid = vt->visual_id;
                msg_Dbg (vd, "using X11 visual ID 0x%"PRIx32, vid);
                sys->depth = fmt->depth;
                msg_Dbg (vd, " %"PRIu8" bits depth", sys->depth);
                msg_Dbg (vd, " %"PRIu8" bits per pixel", fmt->bits_per_pixel);
                msg_Dbg (vd, " %"PRIu8" bits line pad", fmt->scanline_pad);
                goto found_format;
            }
            vt++;
        }

        /* Then try Static Gray class */
        if (fmt->depth != 8)
            continue;
        vt = xcb_depth_visuals (d);
        for (int i = xcb_depth_visuals_length (d); i > 0 && !vid; i--)
        {
            if (vt->_class == XCB_VISUAL_CLASS_STATIC_GRAY)
            {
                fmt_pic.i_chroma = VLC_CODEC_GREY;
                goto found_visual;
            }
            vt++;
        }
    }

    msg_Err (obj, "no supported pixel format & visual");
    goto error;

found_format:;
    /* Create colormap (needed to select non-default visual) */
    xcb_colormap_t cmap;
    if (vid != scr->root_visual)
    {
        cmap = xcb_generate_id (conn);
        xcb_create_colormap (conn, XCB_COLORMAP_ALLOC_NONE,
                             cmap, scr->root, vid);
    }
    else
        cmap = scr->default_colormap;

    /* Create window */
    sys->window = xcb_generate_id (conn);
    sys->gc = xcb_generate_id (conn);
    xcb_pixmap_t pixmap = xcb_generate_id (conn);
    {
        const uint32_t mask =
            XCB_CW_BACK_PIXMAP |
            XCB_CW_BACK_PIXEL |
            XCB_CW_BORDER_PIXMAP |
            XCB_CW_BORDER_PIXEL |
            XCB_CW_EVENT_MASK |
            XCB_CW_COLORMAP;
        const uint32_t values[] = {
            /* XCB_CW_BACK_PIXMAP */
            pixmap,
            /* XCB_CW_BACK_PIXEL */
            scr->black_pixel,
            /* XCB_CW_BORDER_PIXMAP */
            pixmap,
            /* XCB_CW_BORDER_PIXEL */
            scr->black_pixel,
            /* XCB_CW_EVENT_MASK */
            XCB_EVENT_MASK_VISIBILITY_CHANGE,
            /* XCB_CW_COLORMAP */
            cmap,
        };
        xcb_void_cookie_t c;

        xcb_create_pixmap (conn, sys->depth, pixmap, scr->root, 1, 1);
        c = xcb_create_window_checked (conn, sys->depth, sys->window,
                                       sys->embed->handle.xid, 0, 0,
                                       width, height, 0,
                                       XCB_WINDOW_CLASS_INPUT_OUTPUT,
                                       vid, mask, values);
        xcb_map_window (conn, sys->window);
        /* Create graphic context (I wonder why the heck do we need this) */
        xcb_create_gc (conn, sys->gc, sys->window, 0, NULL);

        if (XCB_error_Check (vd, conn, "cannot create X11 window", c))
            goto error;
    }
    msg_Dbg (vd, "using X11 window %08"PRIx32, sys->window);
    msg_Dbg (vd, "using X11 graphic context %08"PRIx32, sys->gc);

    sys->cursor = XCB_cursor_Create (conn, scr);
    sys->visible = false;
    if (XCB_shm_Check (obj, conn))
    {
        sys->seg_base = xcb_generate_id (conn);
        for (unsigned i = 1; i < MAX_PICTURES; i++)
             xcb_generate_id (conn);
    }
    else
        sys->seg_base = 0;

    /* Setup vout_display_t once everything is fine */
    vd->info.has_pictures_invalid = true;
    vd->info.has_event_thread = true;

    vd->fmt = fmt_pic;
    vd->pool = Pool;
    vd->prepare = NULL;
    vd->display = Display;
    vd->control = Control;
    vd->manage = Manage;

    /* */
    bool is_fullscreen = vd->cfg->is_fullscreen;
    if (is_fullscreen && vout_window_SetFullScreen (sys->embed, true))
        is_fullscreen = false;
    vout_display_SendEventFullscreen (vd, is_fullscreen);
    vout_display_SendEventDisplaySize (vd, width, height, is_fullscreen);

    return VLC_SUCCESS;

error:
    Close (obj);
    return VLC_EGENERIC;
}
Ejemplo n.º 8
0
/* Main driver */
int
main (int argc, char **argv)
{
    xcb_connection_t *conn;
    int conn_screen;
    xcb_screen_t *root_screen;
    xcb_drawable_t root_window;
    xcb_connection_t *conn_two;
    int conn_two_screen;
    xcb_screen_t *root_two_screen;
    xcb_drawable_t root_two_window;
    xcb_drawable_t window;

    uint32_t mask;
    uint32_t values[1];

    xcb_void_cookie_t cookie;

    xcb_get_geometry_reply_t *geom_reply;

    xcb_generic_event_t *event;

    image_data_t img_data;
    xcb_image_t *image;
    xcb_pixmap_t pixmap;
    xcb_gcontext_t gc;

    /* Check the first argument to see what display to connect to. If
       empty, then use default display. */
    if (argc > 1) {
      conn = xcb_connect(argv[1], &conn_screen);
    } else {
      conn = xcb_connect(NULL, &conn_screen);
    }
    root_screen = xcb_aux_get_screen(conn, conn_screen);
    root_window = root_screen->root;

    /* Get the geometry of the root window */
    geom_reply = GetWindowGeometry(conn, root_window);
    
    WriteWindowInfo(conn, root_window);
	WriteAllChildrenWindowInfo(conn, root_window);
    img_data = GetWindowImageData(conn, root_window);

	xcb_flush(conn);
    /* Get the image of the root window */
    image = xcb_image_get(conn,
                          root_window,
                          geom_reply->x,
                          geom_reply->y,
                          geom_reply->width,
                          geom_reply->height,
                          (unsigned int) ~0L,
                          XCB_IMAGE_FORMAT_Z_PIXMAP);
    /* Set up the events the window will recognize */
    mask = XCB_CW_EVENT_MASK;
    values[0] = XCB_EVENT_MASK_EXPOSURE | XCB_EVENT_MASK_KEY_PRESS;

    /* Create our new window on the default display. Make it half the size */
    conn_two = xcb_connect(NULL, &conn_two_screen);
    root_two_screen = xcb_aux_get_screen(conn_two, conn_two_screen);
    root_two_window = root_two_screen->root;
    window = xcb_generate_id(conn_two);
    cookie = xcb_create_window_checked(conn_two,
                                       XCB_COPY_FROM_PARENT,
                                       window,
                                       root_two_window,
                                       geom_reply->x,
                                       geom_reply->y,
                                       geom_reply->width / 2,
                                       geom_reply->height / 2,
                                       geom_reply->border_width,
                                       XCB_WINDOW_CLASS_INPUT_OUTPUT,
                                       root_two_screen->root_visual,
                                       mask,
                                       values);
    if (RequestCheck(conn_two, cookie, "Falied to create new window")) {
        exit(1);
    }

    WriteWindowInfo(conn_two, window);
    /* Map the window and flush the connection so it draws to the screen */
    xcb_map_window(conn_two, window);
    xcb_flush(conn_two);
    WriteWindowInfo(conn_two, window);

    /* Create the pixmap and associate it with our new window. */
    pixmap = xcb_generate_id(conn_two);
    cookie = xcb_create_pixmap(conn_two,
                               geom_reply->depth,
                               pixmap,
                               window,
                               geom_reply->width,
                               geom_reply->height);
    if (RequestCheck(conn_two, cookie, "Failed to create pixmap")) {
        exit(1);
    }

    /* Put the root_window image into the pixmap. Note that a gc is
     * created, but I believe it is ignored. */
    gc = xcb_generate_id(conn_two);
    xcb_create_gc(conn_two, gc, window, 0, 0);
    cookie = xcb_image_put(conn_two,
                           pixmap,
                           gc,
                           image,
                           0,
                           0,
                           0);
    if (RequestCheck(conn_two, cookie, "Failed to put image into pixmap")) {
        exit(1);
    }

    /* Copy the pixmap into the new window */
    cookie = xcb_copy_area(conn_two,
                           pixmap,
                           window,
                           gc,
                           0,
                           0,
                           0,
                           0,
                           geom_reply->width / 2,
                           geom_reply->height / 2);
    if (RequestCheck(conn_two, cookie, "Failed to put image into pixmap")) {
        exit(1);
    }
                           
    xcb_flush(conn_two);
    WriteWindowInfo(conn_two, window);

    /* Enter infinte loop so the window stays open */
    while (1) {
    }

    /* Never get here, but if we could, would still want to clean up memory */
    free(geom_reply);
    xcb_disconnect(conn);
    xcb_disconnect(conn_two);

    return 0;
}
Ejemplo n.º 9
0
void draw_byxid(xcb_window_t xid)
{
  xcb_connection_t    *c=G.conn;
  xcb_window_t         w=xid;
  xcb_get_geometry_reply_t *geo;
  uint32_t mask;
  uint32_t values[4];

  geo = xcb_get_geometry_reply(G.conn, 
      xcb_get_geometry(G.conn, w), NULL);
  assert(geo != NULL);

  printf("get (%hdx%hd)@(%dx%d)\n",  
      geo->x, geo->y, geo->width, geo->height);
  // try require event handler, and draw something.

  //start create sub window and draw gc in it.
//  getchar();

  /* create sub window */
  xcb_window_t         child;
  child = xcb_generate_id(c);
	mask = XCB_CW_BACK_PIXEL | XCB_CW_EVENT_MASK;
	values[0] = G.s->black_pixel;
	values[1] = XCB_EVENT_MASK_EXPOSURE | XCB_EVENT_MASK_KEY_PRESS;
  xcb_void_cookie_t cookie;

   // create colormap if needed , window pixfmt is diff from root window.

/*	xcb_map_window(c, w); xcb_flush(c);   */

  //creat a half size window
  geo->width /=2;
  geo->height /=2;

	cookie = xcb_create_window_checked(c, G.s->root_depth, child, w,
      10, 10, geo->width, geo->height,
      1,
			XCB_WINDOW_CLASS_INPUT_OUTPUT, G.s->root_visual,
			mask, values);

  //check cookie error
  if(1){
    xcb_generic_error_t *err;
    err = xcb_request_check (c, cookie);
    if (err){
      int code = err->error_code;
      free (err);
      printf("X11 error %d", code);
      assert (code != 0);
    }
  }
  xcb_map_window(c, child); xcb_flush(c);

  // xcb_reparent_window(c, child,  0,100,100);  
  // root=0 return no affected.
  xcb_reparent_window(c, child,  G.s->root,100,100);
//  xcb_map_window(c, child);xcb_flush(c);

  // ? why make a pixmap as attribute of new sub window
  xcb_pixmap_t      pixmap;
  xcb_create_pixmap (G.conn, geo->depth, pixmap,
      child, geo->width, geo->height);

  values[1] |= XCB_EVENT_MASK_POINTER_MOTION |
     XCB_EVENT_MASK_BUTTON_PRESS | XCB_EVENT_MASK_BUTTON_RELEASE;
  xcb_change_window_attributes_checked(c, child, mask, values); xcb_flush(c);

//  xcb_poly_fill_rectangle(c, child, g,  1, &r);
  // both map and flush need to show window up
  //getchar();
  //unmap is minimum window
//  xcb_unmap_window(c, child);
// xcb_destroy_window(c, child);

  create_dri_drawable();


  int done =0 ;
  xcb_generic_event_t *e;
  printf("wait event\n");
  while (!done ) {
		printf("\re=>(x%x)", e->response_type); fflush(stdout);
    e = xcb_wait_for_event(c);
    if(!e)printf("wait event error\n");
    else{
      switch (e->response_type & ~0x80) {
        case XCB_EXPOSE:    /* draw or redraw the window */
          printf("XCB_EXPOSE\n");
          draw_gc(child);
          break;
        case XCB_KEY_PRESS:  /* exit on key press */
          //gwj done = 1;
          break;
      }
      free(e);
    }
  }
  xcb_unmap_window(c, child);
  xcb_destroy_window(c, child);
}
int main() {
  //get the connection
  int screenNum;
  xcb_connection_t *connection = xcb_connect(NULL, &screenNum);
  if (!connection) {
    fprintf(stderr, "ERROR: can't connect to an X server\n");
    return -1;
  }

  // get the current screen
  xcb_screen_iterator_t iter = xcb_setup_roots_iterator(xcb_get_setup(connection));

  // we want the screen at index screenNum of the iterator
  for (int i = 0; i < screenNum; i++) {
    xcb_screen_next(&iter);
  }
  xcb_screen_t *screen = iter.data;

  if(!screen){
    fprintf(stderr, "ERROR: can't get the current screen\n");
    xcb_disconnect(connection);
    return -1;
  }

  // create the window
  xcb_window_t window = xcb_generate_id(connection);
  uint32_t mask = XCB_CW_BACK_PIXEL |XCB_CW_EVENT_MASK;
  uint32_t values[2];
  values[0] = screen->white_pixel;
  values[1] = XCB_EVENT_MASK_KEY_RELEASE |
              XCB_EVENT_MASK_BUTTON_PRESS |
              XCB_EVENT_MASK_EXPOSURE |
              XCB_EVENT_MASK_POINTER_MOTION;

xcb_void_cookie_t windowCookie = xcb_create_window_checked(connection,
                                                           screen->root_depth,
                                                           window,
                                                           screen->root,
                                                           20,200,WIDTH,HEIGHT,
                                                           0,
                                                           XCB_WINDOW_CLASS_INPUT_OUTPUT,
                                                           screen->root_visual,
                                                           mask, values);

testCookie(windowCookie, connection, "can't create window");

xcb_void_cookie_t mapCookie = xcb_map_window_checked(connection, window);
testCookie(mapCookie, connection, "can't map window");

setCursor(connection, screen, window, 68);
xcb_flush(connection);

// Event loop
uint8_t isHand = 0;

while (1) {
  xcb_generic_event_t *event = xcb_poll_for_event(connection);
  if(event){
    switch (event->response_type & ~0x80) {
      case XCB_EXPOSE: {
        char *text = "click here to change cursor";
        drawButton(connection,
                   screen,
                   window,
                   (WIDTH - 7 * strlen(text)) / 2,
                   (WIDTH -16) / 2,
                   text);

        text = "Press ESC key to exit...";
        drawText(connection,
                 screen,
                 window,
                 10,
                 HEIGHT -10,
                 text);
        break;
      }
      case XCB_BUTTON_PRESS: {
        xcb_button_press_event_t *press = (xcb_button_press_event_t *)event;

        int length = strlen("click here to change cursor");
        if ((press->event_x >= (WIDTH -7 * length) / 2) &&
                (press->event_x <= ((WIDTH -7 * length) /2 + 7 * length + 6)) &&
                (press->event_y >= (HEIGHT -16) / 2 - 19) &&
                (press->event_y <= ((HEIGHT -16) / 2))) {
          isHand = 1 - isHand;
        }
        if (isHand){
          setCursor(connection, screen, window, 58);
        }
        else{
          setCursor(connection, screen, window, 68);
        }
      }
      case XCB_KEY_RELEASE: {
        xcb_key_release_event_t *kr = (xcb_key_release_event_t *)event;

        switch (kr->detail) {
          // ESC
          case 9:
            free(event);
            xcb_disconnect(connection);
            return 0;
        }
      }
    }
    free(event);
  }
}


  return 0;
}
Ejemplo n.º 11
0
  /** \param connection connection to a X sever
      \param screen screen, where the window will be created
      \param parent parent window (0 for screen->root)
      \param windowed means no fullscreen
  */
  scr_window(xcb_connection_t *connection, xcb_screen_t *screen,
             xcb_window_t parent, bool windowed)
    : con(connection), scr(screen), client_win(0)
  {
    uint32_t mask;
    uint32_t values[3];
    xcb_void_cookie_t cookie;
    xcb_generic_error_t *error = NULL;
    if(!parent) parent = scr->root;

    // use parent window size when not in windowed mode
    if(!windowed) {
        xcb_get_geometry_cookie_t geo_cookie = xcb_get_geometry(con, parent);
        xcb_get_geometry_reply_t *reply =
          xcb_get_geometry_reply(con, geo_cookie, &error);
        if(error) {
            std::cerr << "Could not get parent window geometry." << std::endl;
            exit(1);
        }
        width = reply->width;
        height = reply->height;
        free(reply);
    } else {
        // use some defaults in windowed mode
        width = 640;
        height = 480;
    }

    if(windowed) {
        // create a black maybe override-redirected window
        // and register for expose and resize events.
        mask = XCB_CW_BACK_PIXEL | XCB_CW_OVERRIDE_REDIRECT | XCB_CW_EVENT_MASK;
        values[0] = scr->black_pixel;
        values[1] = !windowed; // only if in fullscreen mode, otherwise normal window
        values[2] = XCB_EVENT_MASK_EXPOSURE | XCB_EVENT_MASK_STRUCTURE_NOTIFY;
        win = xcb_generate_id(con);
        cookie = xcb_create_window_checked(
            con, XCB_COPY_FROM_PARENT, win,
            parent, 0, 0, width, height, 0,
            XCB_WINDOW_CLASS_INPUT_OUTPUT,
            scr->root_visual, mask, values
        );
        error = xcb_request_check(con, cookie);
        if(error) {
            std::cerr << "Could not create window." << std::endl;
            exit(1);
        }

        // map the window on the screen
        xcb_map_window(con, win);
        xcb_flush(con);
    } else {
        // directly use the parent window
        win = parent;

        // cahnge window attributes like above
        mask = XCB_CW_BACK_PIXEL | XCB_CW_EVENT_MASK;
        values[0] = scr->black_pixel;
        values[1] = XCB_EVENT_MASK_EXPOSURE;
        xcb_void_cookie_t cookie =
          xcb_change_window_attributes(con, win, mask, values);

        xcb_generic_error_t *error = xcb_request_check(con, cookie);
        if(error) {
            std::cerr << "Could not configure window." << std::endl;
            exit(1);
        }
    } 

    // open a font. "fixed" should hopefully be available everywhere
    font = xcb_generate_id(con);
    std::string font_name = "fixed";
    cookie = xcb_open_font_checked(con, font, font_name.size(),
                                   font_name.c_str());
    error = xcb_request_check(con, cookie);
    if(error) {
        std::cerr << "Could not open font " << font_name << "." << std::endl;
        exit(1);
    }

    // allocate white text graphics context with above font
    txt_gc = xcb_generate_id(con);
    mask = XCB_GC_FOREGROUND | XCB_GC_FONT;
    values[0] = scr->white_pixel;
    values[1] = font;
    cookie = xcb_create_gc_checked(con, txt_gc, win, mask, values);
    error = xcb_request_check(con, cookie);
    if(error) {
        std::cerr << "Could not create graphics context." << std::endl;
        exit(1);
    }
  }
Ejemplo n.º 12
0
int main ()
{
  xcb_screen_iterator_t screen_iter;
  xcb_connection_t     *c;
  const xcb_setup_t    *setup;
  xcb_screen_t         *screen;
  xcb_generic_event_t  *e;
  xcb_generic_error_t  *error;
  xcb_void_cookie_t     cookie_window;
  xcb_void_cookie_t     cookie_map;
  xcb_window_t          window;
  uint32_t              mask;
  uint32_t              values[2];
  int                   screen_number;
  uint8_t               is_hand = 0;

  /* getting the connection */
  c = xcb_connect (NULL, &screen_number);
  if (!c) {
    fprintf (stderr, "ERROR: can't connect to an X server\n");
    return -1;
  }

  /* getting the current screen */
  setup = xcb_get_setup (c);

  screen = NULL;
  screen_iter = xcb_setup_roots_iterator (setup);
  for (; screen_iter.rem != 0; --screen_number, xcb_screen_next (&screen_iter))
    if (screen_number == 0)
      {
        screen = screen_iter.data;
        break;
      }
  if (!screen) {
    fprintf (stderr, "ERROR: can't get the current screen\n");
    xcb_disconnect (c);
    return -1;
  }

  /* creating the window */
  window = xcb_generate_id (c);
  mask = XCB_CW_BACK_PIXEL | XCB_CW_EVENT_MASK;
  values[0] = screen->white_pixel;
  values[1] =
    XCB_EVENT_MASK_KEY_RELEASE |
    XCB_EVENT_MASK_BUTTON_PRESS |
    XCB_EVENT_MASK_EXPOSURE |
    XCB_EVENT_MASK_POINTER_MOTION;
  cookie_window = xcb_create_window_checked (c,
                                             screen->root_depth,
                                             window, screen->root,
                                             20, 200, WIDTH, HEIGHT,
                                             0, XCB_WINDOW_CLASS_INPUT_OUTPUT,
                                             screen->root_visual,
                                             mask, values);
  cookie_map = xcb_map_window_checked (c, window);

  /* error managing */
  error = xcb_request_check (c, cookie_window);
  if (error) {
    fprintf (stderr, "ERROR: can't create window : %d\n", error->error_code);
    xcb_disconnect (c);
    return -1;
  }
  error = xcb_request_check (c, cookie_map);
  if (error) {
    fprintf (stderr, "ERROR: can't map window : %d\n", error->error_code);
    xcb_disconnect (c);
    return -1;
  }

  cursor_set (c, screen, window, 68);

  xcb_flush(c);

  while (1) {
    e = xcb_poll_for_event(c);
    if (e) {
      switch (e->response_type & ~0x80) {
      case XCB_EXPOSE: {
        char *text;

        text = "click here to change cursor";
        button_draw (c, screen, window,
                     (WIDTH - 7 * strlen(text)) / 2,
                     (HEIGHT - 16) / 2, text);

        text = "Press ESC key to exit...";
        text_draw (c, screen, window, 10, HEIGHT - 10, text);
        break;
      }
      case XCB_BUTTON_PRESS: {
        xcb_button_press_event_t *ev;
        int                       length;

        ev = (xcb_button_press_event_t *)e;
        length = strlen ("click here to change cursor");

        if ((ev->event_x >= (WIDTH - 7 * length) / 2) &&
            (ev->event_x <= ((WIDTH - 7 * length) / 2 + 7 * length + 6)) &&
            (ev->event_y >= (HEIGHT - 16) / 2 - 19) &&
            (ev->event_y <= ((HEIGHT - 16) / 2)))
          is_hand = 1 - is_hand;

        is_hand ? cursor_set (c, screen, window, 58) : cursor_set (c, screen, window, 68);
      }
      case XCB_KEY_RELEASE: {
        xcb_key_release_event_t *ev;

        ev = (xcb_key_release_event_t *)e;

        switch (ev->detail) {
          /* ESC */
        case 9:
          free (e);
          xcb_disconnect (c);
          return 0;
        }
      }
      }
      free (e);
    }
  }

  return 0;
}
Ejemplo n.º 13
0
xcbosd *xcbosd_create(xine_t *xine, xcb_connection_t *connection, xcb_screen_t *screen, xcb_window_t window, enum xcbosd_mode mode)
{
  xcbosd *osd;

  xcb_get_geometry_cookie_t get_geometry_cookie;
  xcb_get_geometry_reply_t *get_geometry_reply;

  xcb_void_cookie_t generic_cookie;
  xcb_generic_error_t *generic_error;

  osd = calloc(1, sizeof(xcbosd));
  if (!osd)
    return NULL;

  osd->mode = mode;
  osd->xine = xine;
  osd->connection = connection;
  osd->screen = screen;
  osd->window = window;

  osd->visual = osd->screen->root_visual;

  get_geometry_cookie = xcb_get_geometry(osd->connection, osd->window);
  get_geometry_reply = xcb_get_geometry_reply(osd->connection, get_geometry_cookie, NULL);
  osd->depth = get_geometry_reply->depth;
  osd->width = get_geometry_reply->width;
  osd->height = get_geometry_reply->height;
  free(get_geometry_reply);

  assert(osd->width);
  assert(osd->height);

  switch (mode) {
    case XCBOSD_SHAPED: {
      const xcb_query_extension_reply_t *query_extension_reply = xcb_get_extension_data(osd->connection, &xcb_shape_id);

      if (!query_extension_reply || !query_extension_reply->present) {
	xprintf(osd->xine, XINE_VERBOSITY_LOG, _("x11osd: XShape extension not available. unscaled overlay disabled.\n"));
	goto error2;
      }

      unsigned int window_params[] = { osd->screen->black_pixel, 1, XCB_EVENT_MASK_EXPOSURE };
      osd->u.shaped.window = xcb_generate_id(osd->connection);
      generic_cookie = xcb_create_window_checked(osd->connection, XCB_COPY_FROM_PARENT, osd->u.shaped.window,
			osd->window, 0, 0, osd->width, osd->height, 0, XCB_COPY_FROM_PARENT,
			XCB_COPY_FROM_PARENT, XCB_CW_BACK_PIXEL | XCB_CW_OVERRIDE_REDIRECT | XCB_CW_EVENT_MASK,
			window_params);
      generic_error = xcb_request_check(osd->connection, generic_cookie);

      if (generic_error != NULL) {
	xprintf(osd->xine, XINE_VERBOSITY_LOG, _("x11osd: error creating window. unscaled overlay disabled.\n"));
	free(generic_error);
	goto error_window;
      }

      osd->u.shaped.mask_bitmap = xcb_generate_id(osd->connection);
      generic_cookie = xcb_create_pixmap_checked(osd->connection, 1, osd->u.shaped.mask_bitmap, osd->u.shaped.window, osd->width, osd->height);
      generic_error = xcb_request_check(osd->connection, generic_cookie);

      if (generic_error != NULL) {
	xprintf(osd->xine, XINE_VERBOSITY_LOG, _("x11osd: error creating pixmap. unscaled overlay disabled.\n"));
	free(generic_error);
	goto error_aftermaskbitmap;
      }

      osd->bitmap = xcb_generate_id(osd->connection);
      xcb_create_pixmap(osd->connection, osd->depth, osd->bitmap, osd->u.shaped.window, osd->width, osd->height);
      osd->gc = xcb_generate_id(osd->connection);
      xcb_create_gc(osd->connection, osd->gc, osd->u.shaped.window, 0, NULL);

      osd->u.shaped.mask_gc = xcb_generate_id(osd->connection);
      xcb_create_gc(osd->connection, osd->u.shaped.mask_gc, osd->u.shaped.mask_bitmap, XCB_GC_FOREGROUND, &osd->screen->white_pixel);

      osd->u.shaped.mask_gc_back = xcb_generate_id(osd->connection);
      xcb_create_gc(osd->connection, osd->u.shaped.mask_gc_back, osd->u.shaped.mask_bitmap, XCB_GC_FOREGROUND, &osd->screen->black_pixel);

      osd->u.shaped.mapped = 0;
      osd->cmap = xcb_generate_id(osd->connection);
      xcb_create_colormap(osd->connection, XCB_COLORMAP_ALLOC_NONE, osd->cmap, osd->u.shaped.window, osd->visual);
      break;
      }
    case XCBOSD_COLORKEY:
      osd->bitmap = xcb_generate_id(osd->connection);
      xcb_create_pixmap(osd->connection, osd->depth, osd->bitmap, osd->window, osd->width, osd->height);
      osd->gc = xcb_generate_id(osd->connection);
      xcb_create_gc(osd->connection, osd->gc, osd->window, 0, NULL);
      osd->cmap = xcb_generate_id(osd->connection);
      xcb_create_colormap(osd->connection, XCB_COLORMAP_ALLOC_NONE, osd->cmap, osd->window, osd->visual);
      /* FIXME: the expose event doesn't seem to happen? */
      /*XSelectInput (osd->display, osd->window, ExposureMask);*/
      break;
    default:
      goto error2;
  }

  osd->clean = UNDEFINED;
  xcbosd_expose(osd);

  xprintf(osd->xine, XINE_VERBOSITY_DEBUG,
    _("x11osd: unscaled overlay created (%s mode).\n"),
    (mode==XCBOSD_SHAPED) ? "XShape" : "Colorkey" );

  return osd;

/*
  XFreeGC (osd->display, osd->gc);
  XFreeGC (osd->display, osd->mask_gc);
  XFreeGC (osd->display, osd->mask_gc_back);
*/

error_aftermaskbitmap:
  if(mode==XCBOSD_SHAPED)
    xcb_free_pixmap(osd->connection, osd->u.shaped.mask_bitmap);
error_window:
  if(mode==XCBOSD_SHAPED)
    xcb_destroy_window(osd->connection, osd->u.shaped.window);
error2:
  free (osd);
  return NULL;
}
Ejemplo n.º 14
0
struct rtb_window *
window_impl_open(struct rutabaga *rtb,
                 int w, int h, const char *title, intptr_t parent)
{
    struct xcb_rutabaga *xrtb = (void *) rtb;
    struct xrtb_window *self;

    Display *dpy;
    xcb_connection_t *xcb_conn;

    int default_screen;

    GLXFBConfig *fb_configs, fb_config;
    XVisualInfo *visual;
    int nfb_configs;

    uint32_t event_mask =
        XCB_EVENT_MASK_STRUCTURE_NOTIFY | XCB_EVENT_MASK_EXPOSURE |
        XCB_EVENT_MASK_VISIBILITY_CHANGE | XCB_EVENT_MASK_BUTTON_PRESS |
        XCB_EVENT_MASK_BUTTON_RELEASE | XCB_EVENT_MASK_POINTER_MOTION |
        XCB_EVENT_MASK_ENTER_WINDOW | XCB_EVENT_MASK_LEAVE_WINDOW |
        XCB_EVENT_MASK_KEY_PRESS | XCB_EVENT_MASK_KEY_RELEASE |
        XCB_EVENT_MASK_KEYMAP_STATE;
    uint32_t value_mask =
        XCB_CW_BORDER_PIXEL | XCB_CW_BACK_PIXMAP |
        XCB_CW_BIT_GRAVITY |
        XCB_CW_EVENT_MASK | XCB_CW_COLORMAP;
    uint32_t value_list[6];

    xcb_colormap_t colormap;
    xcb_void_cookie_t ck_window, ck_map;
    xcb_generic_error_t *err;

    assert(rtb);
    assert(h > 0);
    assert(w > 0);

    if (!(self = calloc(1, sizeof(*self))))
        goto err_malloc;

    self->xrtb = xrtb;

    dpy = xrtb->dpy;
    xcb_conn = xrtb->xcb_conn;

    default_screen = DefaultScreen(dpy);

    self->screen = find_xcb_screen(xcb_conn, default_screen);
    if (!self->screen) {
        ERR("couldn't find XCB screen\n");
        goto err_screen;
    }

    /**
     * gl configuration
     */

    fb_configs = glXGetFBConfigs(dpy, default_screen, &nfb_configs);
    if (!fb_configs || !nfb_configs) {
        ERR("no GL configurations, bailing out\n");
        goto err_gl_config;
    }

    fb_config = find_reasonable_fb_config(dpy, xcb_conn, fb_configs,
                                          nfb_configs, 0);

    if (!fb_config) {
        ERR("no reasonable GL configurations, bailing out\n");
        goto err_gl_config;
    }

    visual = glXGetVisualFromFBConfig(dpy, fb_config);

    self->gl_ctx = new_gl_context(dpy, fb_config);
    if (!self->gl_ctx) {
        ERR("couldn't create GLX context\n");
        goto err_gl_ctx;
    }

    /**
     * window setup
     */

    colormap = xcb_generate_id(xcb_conn);
    self->xcb_win = xcb_generate_id(xcb_conn);

    xcb_create_colormap(
        xcb_conn, XCB_COLORMAP_ALLOC_NONE, colormap,
        self->screen->root, visual->visualid);

    value_list[0] = 0;
    value_list[1] = 0;
    value_list[2] = XCB_GRAVITY_STATIC;
    value_list[3] = event_mask;
    value_list[4] = colormap;
    value_list[5] = 0;

    ck_window = xcb_create_window_checked(
                    xcb_conn, visual->depth, self->xcb_win,
                    parent ? (xcb_window_t) parent : self->screen->root,
                    0, 0,
                    w, h,
                    0,
                    XCB_WINDOW_CLASS_INPUT_OUTPUT,
                    visual->visualid, value_mask, value_list);

    free(visual);

    if ((err = xcb_request_check(xcb_conn, ck_window))) {
        ERR("can't create XCB window: %d\n", err->error_code);
        goto err_xcb_win;
    }

    get_dpi(dpy, default_screen, &self->dpi.x, &self->dpi.y);

    self->gl_win = glXCreateWindow(dpy, fb_config, self->xcb_win, 0);
    if (!self->gl_win) {
        ERR("couldn't create GL window\n");
        goto err_gl_win;
    }

    if (set_xprop(xcb_conn, self->xcb_win, XCB_ATOM_WM_NAME, title))
        set_xprop(xcb_conn, self->xcb_win, XCB_ATOM_WM_NAME, "oh no");

    self->gl_draw = self->gl_win;

    if (!glXMakeContextCurrent(
                dpy, self->gl_draw, self->gl_draw, self->gl_ctx)) {
        ERR("couldn't activate GLX context\n");
        goto err_gl_make_current;
    }

    ck_map = xcb_map_window_checked(xcb_conn, self->xcb_win);
    if ((err = xcb_request_check(xcb_conn, ck_map))) {
        ERR("can't map XCB window: %d\n", err->error_code);
        goto err_win_map;
    }

    if (parent)
        raise_window(xcb_conn, self->xcb_win);
    else
        xcb_icccm_set_wm_protocols(xcb_conn,
                                   self->xcb_win, xrtb->atoms.wm_protocols,
                                   1, &xrtb->atoms.wm_delete_window);

    free(fb_configs);

    uv_mutex_init(&self->lock);
    return RTB_WINDOW(self);

err_win_map:
err_gl_make_current:
err_gl_win:
    xcb_destroy_window(xcb_conn, self->xcb_win);

err_xcb_win:
    glXDestroyContext(dpy, self->gl_ctx);

err_gl_ctx:
err_gl_config:
    free(fb_configs);
err_screen:
    free(self);

err_malloc:
    return NULL;
}
Ejemplo n.º 15
0
static cairo_surface_t *
_cairo_boilerplate_xcb_create_fallback (const char		  *name,
					cairo_content_t 	   content,
					double			   width,
					double			   height,
					double			   max_width,
					double			   max_height,
					cairo_boilerplate_mode_t   mode,
					int			   id,
					void			 **closure)
{
    xcb_target_closure_t *xtc;
    xcb_connection_t *c;
    xcb_screen_t *s;
    xcb_void_cookie_t cookie;
    cairo_surface_t *tmp, *surface;
    cairo_status_t status;
    uint32_t values[] = { 1 };

    *closure = xtc = xmalloc (sizeof (xcb_target_closure_t));

    if (width == 0)
	width = 1;
    if (height == 0)
	height = 1;

    xtc->c = c = xcb_connect (NULL,NULL);
    if (xcb_connection_has_error(c)) {
	free (xtc);
	return NULL;
    }

    s = xcb_setup_roots_iterator (xcb_get_setup (c)).data;
    if (width > s->width_in_pixels || height > s->height_in_pixels) {
	xcb_disconnect (c);
	free (xtc);
	return NULL;
    }

    xtc->surface = NULL;
    xtc->is_pixmap = FALSE;
    xtc->drawable = xcb_generate_id (c);
    cookie = xcb_create_window_checked (c,
					s->root_depth,
					xtc->drawable,
					s->root,
					0, 0, width, height, 0,
					XCB_WINDOW_CLASS_INPUT_OUTPUT,
					s->root_visual,
					XCB_CW_OVERRIDE_REDIRECT,
					values);
    xcb_map_window (c, xtc->drawable);

    /* slow, but sure */
    if (xcb_request_check (c, cookie) != NULL) {
	xcb_disconnect (c);
	free (xtc);
	return NULL;
    }

    tmp = cairo_xcb_surface_create (c,
				    xtc->drawable,
				    lookup_visual (s, s->root_visual),
				    width, height);
    if (cairo_surface_status (tmp)) {
	xcb_disconnect (c);
	free (xtc);
	return tmp;
    }

    cairo_xcb_device_debug_cap_xrender_version (cairo_surface_get_device (tmp),
						-1, -1);
    /* recreate with impaired connection */
    surface = cairo_xcb_surface_create (c,
					xtc->drawable,
					lookup_visual (s, s->root_visual),
					width, height);
    cairo_surface_destroy (tmp);

    xtc->device = cairo_device_reference (cairo_surface_get_device (surface));
    status = cairo_surface_set_user_data (surface, &xcb_closure_key, xtc, NULL);
    if (status == CAIRO_STATUS_SUCCESS)
	return surface;

    cairo_surface_destroy (surface);

    _cairo_boilerplate_xcb_cleanup (xtc);
    return cairo_boilerplate_surface_create_in_error (status);
}
Ejemplo n.º 16
0
/**
 * Create an X11 window.
 */
static int Open (vout_window_t *wnd, const vout_window_cfg_t *cfg)
{
    xcb_generic_error_t *err;
    xcb_void_cookie_t ck;

    vout_window_sys_t *p_sys = malloc (sizeof (*p_sys));
    if (p_sys == NULL)
        return VLC_ENOMEM;
    p_sys->embedded = false;

    /* Connect to X */
    char *display = var_InheritString (wnd, "x11-display");
    int snum;

    xcb_connection_t *conn = xcb_connect (display, &snum);
    if (xcb_connection_has_error (conn) /*== NULL*/)
        goto error;

    /* Find configured screen */
    const xcb_setup_t *setup = xcb_get_setup (conn);
    const xcb_screen_t *scr = NULL;
    for (xcb_screen_iterator_t i = xcb_setup_roots_iterator (setup);
         i.rem > 0; xcb_screen_next (&i))
    {
        if (snum == 0)
        {
            scr = i.data;
            break;
        }
        snum--;
    }
    if (scr == NULL)
    {
        msg_Err (wnd, "bad X11 screen number");
        goto error;
    }

    /* Create window */
    const uint32_t mask = XCB_CW_BACK_PIXEL | XCB_CW_EVENT_MASK;
    uint32_t values[2] = {
        /* XCB_CW_BACK_PIXEL */
        scr->black_pixel,
        /* XCB_CW_EVENT_MASK */
        XCB_EVENT_MASK_KEY_PRESS,
    };

    xcb_window_t window = xcb_generate_id (conn);
    ck = xcb_create_window_checked (conn, scr->root_depth, window, scr->root,
                                    cfg->x, cfg->y, cfg->width, cfg->height, 0,
                                    XCB_WINDOW_CLASS_INPUT_OUTPUT,
                                    scr->root_visual, mask, values);
    err = xcb_request_check (conn, ck);
    if (err)
    {
        msg_Err (wnd, "creating window: X11 error %d", err->error_code);
        free (err);
        goto error;
    }

    wnd->handle.xid = window;
    wnd->display.x11 = display;
    wnd->control = Control;
    wnd->sys = p_sys;

    p_sys->conn = conn;
    if (var_InheritBool (wnd, "keyboard-events"))
        p_sys->keys = CreateKeyHandler (VLC_OBJECT(wnd), conn);
    else
        p_sys->keys = NULL;
    p_sys->root = scr->root;

    /* ICCCM
     * No cut&paste nor drag&drop, only Window Manager communication. */
    set_ascii_prop (conn, window, XA_WM_NAME,
    /* xgettext: This is a plain ASCII spelling of "VLC media player"
       for the ICCCM window name. This must be pure ASCII.
       The limitation is partially with ICCCM and partially with VLC.
       For Latin script languages, you may need to strip accents.
       For other scripts, you will need to transliterate into Latin. */
                    vlc_pgettext ("ASCII", "VLC media player"));

    set_ascii_prop (conn, window, XA_WM_ICON_NAME,
    /* xgettext: This is a plain ASCII spelling of "VLC"
       for the ICCCM window name. This must be pure ASCII. */
                    vlc_pgettext ("ASCII", "VLC"));
    set_wm_hints (conn, window);
    xcb_change_property (conn, XCB_PROP_MODE_REPLACE, window, XA_WM_CLASS,
                         XA_STRING, 8, 8, "vlc\0Vlc");
    set_hostname_prop (conn, window);

    /* EWMH */
    xcb_intern_atom_cookie_t utf8_string_ck
        = intern_string (conn, "UTF8_STRING");;
    xcb_intern_atom_cookie_t net_wm_name_ck
        = intern_string (conn, "_NET_WM_NAME");
    xcb_intern_atom_cookie_t net_wm_icon_name_ck
        = intern_string (conn, "_NET_WM_ICON_NAME");
    xcb_intern_atom_cookie_t wm_window_role_ck
        = intern_string (conn, "WM_WINDOW_ROLE");

    xcb_atom_t utf8 = get_atom (conn, utf8_string_ck);

    xcb_atom_t net_wm_name = get_atom (conn, net_wm_name_ck);
    char *title = var_InheritString (wnd, "video-title");
    if (title)
    {
        set_string (conn, window, utf8, net_wm_name, title);
        free (title);
    }
    else
        set_string (conn, window, utf8, net_wm_name, _("VLC media player"));

    xcb_atom_t net_wm_icon_name = get_atom (conn, net_wm_icon_name_ck);
    set_string (conn, window, utf8, net_wm_icon_name, _("VLC"));

    xcb_atom_t wm_window_role = get_atom (conn, wm_window_role_ck);
    set_ascii_prop (conn, window, wm_window_role, "vlc-video");

    /* Cache any EWMH atom we may need later */
    CacheAtoms (p_sys);

    /* Make the window visible */
    xcb_map_window (conn, window);

    if (var_InheritBool (wnd, "video-wallpaper"))
    {
        vout_window_SetState (wnd, VOUT_WINDOW_STATE_BELOW);
        vout_window_SetFullScreen (wnd, true);
    }

    /* Create the event thread. It will dequeue all events, so any checked
     * request from this thread must be completed at this point. */
    if ((p_sys->keys != NULL)
     && vlc_clone (&p_sys->thread, Thread, wnd, VLC_THREAD_PRIORITY_LOW))
        DestroyKeyHandler (p_sys->keys);

    xcb_flush (conn); /* Make sure map_window is sent (should be useless) */
    return VLC_SUCCESS;

error:
    xcb_disconnect (conn);
    free (display);
    free (p_sys);
    return VLC_EGENERIC;
}
Ejemplo n.º 17
0
Archivo: x11.c Proyecto: paa/vlc
/**
 * Probe the X server.
 */
static int Open (vlc_object_t *obj)
{
    vout_display_t *vd = (vout_display_t *)obj;
    vout_display_sys_t *p_sys = malloc (sizeof (*p_sys));
    if (p_sys == NULL)
        return VLC_ENOMEM;

    vd->sys = p_sys;
    p_sys->pool = NULL;

    /* Get window, connect to X server */
    const xcb_screen_t *scr;
    p_sys->embed = GetWindow (vd, &p_sys->conn, &scr, &(uint8_t){ 0 });
    if (p_sys->embed == NULL)
    {
        free (p_sys);
        return VLC_EGENERIC;
    }

    const xcb_setup_t *setup = xcb_get_setup (p_sys->conn);
    p_sys->byte_order = setup->image_byte_order;

    /* Determine our pixel format */
    xcb_visualid_t vid = 0;
    p_sys->depth = 0;

    for (const xcb_format_t *fmt = xcb_setup_pixmap_formats (setup),
             *end = fmt + xcb_setup_pixmap_formats_length (setup);
         fmt < end;
         fmt++)
    {
        if (fmt->depth <= p_sys->depth)
            continue; /* no better than earlier format */

        video_format_t fmt_pic = vd->fmt;

        /* Check that the pixmap format is supported by VLC. */
        switch (fmt->depth)
        {
          case 32:
            if (fmt->bits_per_pixel != 32)
                continue;
#ifdef FIXED_VLC_RGBA_MASK
            fmt_pic.i_chroma = VLC_CODEC_RGBA;
            break;
#else
            msg_Dbg (vd, "X11 visual with alpha-channel not supported");
            continue;
#endif
          case 24:
            if (fmt->bits_per_pixel == 32)
                fmt_pic.i_chroma = VLC_CODEC_RGB32;
            else if (fmt->bits_per_pixel == 24)
                fmt_pic.i_chroma = VLC_CODEC_RGB24;
            else
                continue;
            break;
          case 16:
            if (fmt->bits_per_pixel != 16)
                continue;
            fmt_pic.i_chroma = VLC_CODEC_RGB16;
            break;
          case 15:
            if (fmt->bits_per_pixel != 16)
                continue;
            fmt_pic.i_chroma = VLC_CODEC_RGB15;
            break;
          case 8:
            if (fmt->bits_per_pixel != 8)
                continue;
            fmt_pic.i_chroma = VLC_CODEC_RGB8;
            break;
          default:
            continue;
        }

        /* VLC pads lines to 16 pixels internally */
        if ((fmt->bits_per_pixel << 4) % fmt->scanline_pad)
            continue;

        /* Byte sex is a non-issue for 8-bits. It can be worked around with
         * RGB masks for 24-bits. Too bad for 15-bits and 16-bits. */
        if (fmt->bits_per_pixel == 16 && setup->image_byte_order != ORDER)
            continue;

        /* Check that the selected screen supports this depth */
        const xcb_depth_t *d = FindDepth (scr, fmt->depth);
        if (d == NULL)
            continue;

        /* Find a visual type for the selected depth */
        const xcb_visualtype_t *vt = xcb_depth_visuals (d);

        /* First try True Color class */
        for (int i = xcb_depth_visuals_length (d); i > 0; i--)
        {
            if (vt->_class == XCB_VISUAL_CLASS_TRUE_COLOR)
            {
                fmt_pic.i_rmask = vt->red_mask;
                fmt_pic.i_gmask = vt->green_mask;
                fmt_pic.i_bmask = vt->blue_mask;
                goto found_visual;
            }
            vt++;
        }
        /* Then try Static Gray class */
        if (fmt->depth == 8)
            for (int i = xcb_depth_visuals_length (d); i > 0 && !vid; i--)
            {
                if (vt->_class == XCB_VISUAL_CLASS_STATIC_GRAY)
                    goto found_grey;
                vt++;
            }

        continue; /* Fail: unusable pixel format */

    found_grey:
       fmt_pic.i_chroma = VLC_CODEC_GREY;
    found_visual:
        p_sys->bpp = fmt->bits_per_pixel;
        p_sys->pad = fmt->scanline_pad;
        p_sys->depth = fmt->depth;
        vd->fmt = fmt_pic;
        vid = vt->visual_id;
    }

    if (!vid)
    {
        msg_Err (obj, "no supported pixel format & visual");
        goto error;
    }

    msg_Dbg (vd, "using X11 visual ID 0x%"PRIx32, vid);
    msg_Dbg (vd, " %"PRIu8" bits depth", p_sys->depth);
    msg_Dbg (vd, " %"PRIu8" bits per pixel", p_sys->bpp);
    msg_Dbg (vd, " %"PRIu8" bits line pad", p_sys->pad);

    /* Create colormap (needed to select non-default visual) */
    xcb_colormap_t cmap;
    if (vid != scr->root_visual)
    {
        cmap = xcb_generate_id (p_sys->conn);
        xcb_create_colormap (p_sys->conn, XCB_COLORMAP_ALLOC_NONE,
                             cmap, scr->root, vid);
    }
    else
        cmap = scr->default_colormap;

    /* Create window */
    unsigned width, height;
    if (GetWindowSize (p_sys->embed, p_sys->conn, &width, &height))
        goto error;

    p_sys->window = xcb_generate_id (p_sys->conn);
    p_sys->gc = xcb_generate_id (p_sys->conn);
    xcb_pixmap_t pixmap = xcb_generate_id (p_sys->conn);
    {
        const uint32_t mask =
            XCB_CW_BACK_PIXMAP |
            XCB_CW_BACK_PIXEL |
            XCB_CW_BORDER_PIXMAP |
            XCB_CW_BORDER_PIXEL |
            XCB_CW_EVENT_MASK |
            XCB_CW_COLORMAP;
        const uint32_t values[] = {
            /* XCB_CW_BACK_PIXMAP */
            pixmap,
            /* XCB_CW_BACK_PIXEL */
            scr->black_pixel,
            /* XCB_CW_BORDER_PIXMAP */
            pixmap,
            /* XCB_CW_BORDER_PIXEL */
            scr->black_pixel,
            /* XCB_CW_EVENT_MASK */
            XCB_EVENT_MASK_VISIBILITY_CHANGE,
            /* XCB_CW_COLORMAP */
            cmap,
        };
        xcb_void_cookie_t c;

        xcb_create_pixmap (p_sys->conn, p_sys->depth, pixmap, scr->root, 1, 1);
        c = xcb_create_window_checked (p_sys->conn, p_sys->depth,
                                       p_sys->window,
                                       p_sys->embed->handle.xid, 0, 0,
                                       width, height, 0,
                                       XCB_WINDOW_CLASS_INPUT_OUTPUT,
                                       vid, mask, values);
        xcb_map_window (p_sys->conn, p_sys->window);
        /* Create graphic context (I wonder why the heck do we need this) */
        xcb_create_gc (p_sys->conn, p_sys->gc, p_sys->window, 0, NULL);

        if (CheckError (vd, p_sys->conn, "cannot create X11 window", c))
            goto error;
    }
    msg_Dbg (vd, "using X11 window %08"PRIx32, p_sys->window);
    msg_Dbg (vd, "using X11 graphic context %08"PRIx32, p_sys->gc);
    p_sys->cursor = CreateBlankCursor (p_sys->conn, scr);

    p_sys->visible = false;

    CheckSHM (obj, p_sys->conn, &p_sys->shm);

    /* */
    vout_display_info_t info = vd->info;
    info.has_pictures_invalid = true;

    /* Setup vout_display_t once everything is fine */
    vd->info = info;

    vd->pool = Pool;
    vd->prepare = NULL;
    vd->display = Display;
    vd->control = Control;
    vd->manage = Manage;

    /* */
    vout_display_SendEventFullscreen (vd, false);
    vout_display_SendEventDisplaySize (vd, width, height, false);

    return VLC_SUCCESS;

error:
    Close (obj);
    return VLC_EGENERIC;
}