Пример #1
0
    std::vector<std::shared_ptr<monitor_t>> get_list(xcb_connection_t *connection, xcb_window_t root)
    {
      std::vector<std::shared_ptr<monitor_t>> monitors;

      xcb_randr_get_screen_resources_reply_t *sres =
        xcb_randr_get_screen_resources_reply(connection,
          xcb_randr_get_screen_resources(connection, root), nullptr);

      if (sres == nullptr)
        return monitors;

      int len = xcb_randr_get_screen_resources_outputs_length(sres);
      xcb_randr_output_t *outputs = xcb_randr_get_screen_resources_outputs(sres);

      for (int i = 0; i < len; i++) {
        xcb_randr_get_output_info_cookie_t cookie =
          xcb_randr_get_output_info(connection, outputs[i], XCB_CURRENT_TIME);
        xcb_randr_get_output_info_reply_t *info =
          xcb_randr_get_output_info_reply(connection, cookie, nullptr);
        xcb_randr_get_output_info(connection, outputs[i], XCB_CURRENT_TIME);

        if (info == nullptr)
          continue;

        if (info->crtc == XCB_NONE) {
          free(info);
          continue;
        }

        xcb_randr_get_crtc_info_reply_t *cir =
          xcb_randr_get_crtc_info_reply(connection,
            xcb_randr_get_crtc_info(connection, info->crtc, XCB_CURRENT_TIME), nullptr);

        if (cir == nullptr) {
          free(info);
          continue;
        }

        char *monitor_name = (char *) xcb_randr_get_output_info_name(info);
        monitors.emplace_back(make_object(monitor_name, info->name_len, i,
            {cir->x, cir->y, cir->width, cir->height}));

        free(cir);
      }

      std::sort(monitors.begin(), monitors.end(), [](std::shared_ptr<monitor_t> m1, std::shared_ptr<monitor_t> m2) -> bool
      {
        if (m1->bounds.x < m2->bounds.x || m1->bounds.y + m1->bounds.height <= m2->bounds.y)
          return 1;
        if (m1->bounds.x > m2->bounds.x || m1->bounds.y + m1->bounds.height > m2->bounds.y)
          return -1;
        return 0;
      });

      return monitors;
    }
Пример #2
0
/* Get the number of outputs */
static unsigned CountMonitors( vlc_object_t *obj )
{
    char *psz_display = var_InheritString( obj, "x11-display" );
    int snum;
    xcb_connection_t *conn = xcb_connect( psz_display, &snum );
    free( psz_display );
    if( xcb_connection_has_error( conn ) )
        return 0;

    const xcb_setup_t *setup = xcb_get_setup( conn );
    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--;
    }

    unsigned n = 0;
    if( scr == NULL )
        goto error;

    xcb_randr_query_version_reply_t *v =
        xcb_randr_query_version_reply( conn,
            xcb_randr_query_version( conn, 1, 2 ), NULL );
    if( v == NULL )
        goto error;
    msg_Dbg( obj, "using X RandR extension v%"PRIu32".%"PRIu32,
             v->major_version, v->minor_version );
    free( v );

    xcb_randr_get_screen_resources_reply_t *r =
        xcb_randr_get_screen_resources_reply( conn,
            xcb_randr_get_screen_resources( conn, scr->root ), NULL );
    if( r == NULL )
        goto error;

    const xcb_randr_output_t *outputs =
        xcb_randr_get_screen_resources_outputs( r );
    for( unsigned i = 0; i < r->num_outputs; i++ )
    {
        xcb_randr_get_output_info_reply_t *output =
            xcb_randr_get_output_info_reply( conn,
                xcb_randr_get_output_info( conn, outputs[i], 0 ), NULL );
        if( output == NULL )
            continue;
        /* FIXME: do not count cloned outputs multiple times */
        /* XXX: what to do with UNKNOWN state connections? */
        n += output->connection == XCB_RANDR_CONNECTION_CONNECTED;
        free( output );
    }
    free( r );
    msg_Dbg( obj, "X randr has %u outputs", n );

error:
    xcb_disconnect( conn );
    return n;
}
Пример #3
0
bool update_monitors(void)
{
	xcb_randr_get_screen_resources_reply_t *sres = xcb_randr_get_screen_resources_reply(dpy, xcb_randr_get_screen_resources(dpy, root), NULL);
	if (sres == NULL) {
		return false;
	}

	monitor_t *m, *mm = NULL;

	int len = xcb_randr_get_screen_resources_outputs_length(sres);
	xcb_randr_output_t *outputs = xcb_randr_get_screen_resources_outputs(sres);

	xcb_randr_get_output_info_cookie_t cookies[len];
	for (int i = 0; i < len; i++) {
		cookies[i] = xcb_randr_get_output_info(dpy, outputs[i], XCB_CURRENT_TIME);
	}

	for (m = mon_head; m != NULL; m = m->next) {
		m->wired = false;
	}

	for (int i = 0; i < len; i++) {
		xcb_randr_get_output_info_reply_t *info = xcb_randr_get_output_info_reply(dpy, cookies[i], NULL);
		if (info != NULL) {
			if (info->crtc != XCB_NONE) {
				xcb_randr_get_crtc_info_reply_t *cir = xcb_randr_get_crtc_info_reply(dpy, xcb_randr_get_crtc_info(dpy, info->crtc, XCB_CURRENT_TIME), NULL);
				if (cir != NULL) {
					xcb_rectangle_t rect = (xcb_rectangle_t) {cir->x, cir->y, cir->width, cir->height};
					mm = get_monitor_by_randr_id(outputs[i]);
					if (mm != NULL) {
						update_root(mm, &rect);
						mm->wired = true;
					} else {
						mm = make_monitor(&rect, XCB_NONE);
						char *name = (char *)xcb_randr_get_output_info_name(info);
						int len = xcb_randr_get_output_info_name_length(info);
						size_t name_size = MIN(sizeof(mm->name), (size_t) len + 1);
						snprintf(mm->name, name_size, "%s", name);
						mm->randr_id = outputs[i];
						add_monitor(mm);
					}
				}
				free(cir);
			} else if (!remove_disabled_monitors && info->connection != XCB_RANDR_CONNECTION_DISCONNECTED) {
				m = get_monitor_by_randr_id(outputs[i]);
				if (m != NULL) {
					m->wired = true;
				}
			}
		}
		free(info);
	}

	xcb_randr_get_output_primary_reply_t *gpo = xcb_randr_get_output_primary_reply(dpy, xcb_randr_get_output_primary(dpy, root), NULL);
	if (gpo != NULL) {
		pri_mon = get_monitor_by_randr_id(gpo->output);
	}
	free(gpo);

	/* handle overlapping monitors */
	if (merge_overlapping_monitors) {
		m = mon_head;
		while (m != NULL) {
			monitor_t *next = m->next;
			if (m->wired) {
				monitor_t *mb = mon_head;
				while (mb != NULL) {
					monitor_t *mb_next = mb->next;
					if (m != mb && mb->wired && contains(m->rectangle, mb->rectangle)) {
						if (mm == mb) {
							mm = m;
						}
						if (next == mb) {
							next = mb_next;
						}
						merge_monitors(mb, m);
						remove_monitor(mb);
					}
					mb = mb_next;
				}
			}
			m = next;
		}
	}

	/* merge and remove disconnected monitors */
	if (remove_unplugged_monitors) {
		m = mon_head;
		while (m != NULL) {
			monitor_t *next = m->next;
			if (!m->wired) {
				merge_monitors(m, mm);
				remove_monitor(m);
			}
			m = next;
		}
	}

	/* add one desktop to each new monitor */
	for (m = mon_head; m != NULL; m = m->next) {
		if (m->desk == NULL) {
			add_desktop(m, make_desktop(NULL, XCB_NONE));
		}
	}

	if (!running && mon != NULL) {
		if (pri_mon != NULL) {
			mon = pri_mon;
		}
		center_pointer(mon->rectangle);
		ewmh_update_current_desktop();
	}

	free(sres);

	return (mon != NULL);
}