weston-info: client that print out information about the running compositor

This includes seat capabilities, shm formats and output information.
dev
Philipp Brüschweiler 12 years ago committed by Kristian Høgsberg
parent 48cd58b25c
commit 585acb0013
  1. 1
      clients/.gitignore
  2. 7
      clients/Makefile.am
  3. 475
      clients/weston-info.c
  4. 1
      configure.ac

@ -29,3 +29,4 @@ editor
text-protocol.c
text-client-protocol.h
keyboard
weston-info

@ -54,6 +54,7 @@ clients_programs = \
clickdot \
editor \
keyboard \
weston-info \
$(full_gl_client_programs)
desktop_shell = weston-desktop-shell
@ -114,6 +115,12 @@ keyboard_SOURCES = \
text-protocol.c
keyboard_LDADD = $(toolkit_libs)
weston_info_SOURCES = \
weston-info.c \
../shared/os-compatibility.c \
../shared/os-compatibility.h
weston_info_LDADD = $(WESTON_INFO_LIBS)
weston_desktop_shell_SOURCES = \
desktop-shell.c \
desktop-shell-client-protocol.h \

@ -0,0 +1,475 @@
/*
* Copyright © 2012 Philipp Brüschweiler
*
* Permission to use, copy, modify, distribute, and sell this software and
* its documentation for any purpose is hereby granted without fee, provided
* that the above copyright notice appear in all copies and that both that
* copyright notice and this permission notice appear in supporting
* documentation, and that the name of the copyright holders not be used in
* advertising or publicity pertaining to distribution of the software
* without specific, written prior permission. The copyright holders make
* no representations about the suitability of this software for any
* purpose. It is provided "as is" without express or implied warranty.
*
* THE COPYRIGHT HOLDERS DISCLAIM ALL WARRANTIES WITH REGARD TO THIS
* SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND
* FITNESS, IN NO EVENT SHALL THE COPYRIGHT HOLDERS BE LIABLE FOR ANY
* SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER
* RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF
* CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN
* CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
*/
#include <stdbool.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <sys/epoll.h>
#include <sys/timerfd.h>
#include <wayland-client.h>
#include "../shared/os-compatibility.h"
typedef void (*print_info_t)(void *info);
struct global_info {
struct wl_list link;
uint32_t id;
uint32_t version;
char *interface;
print_info_t print;
};
struct output_info {
struct global_info global;
struct wl_output *output;
struct {
int32_t x, y;
int32_t physical_width, physical_height;
enum wl_output_subpixel subpixel;
enum wl_output_transform output_transform;
char *make;
char *model;
} geometry;
struct {
uint32_t flags;
int32_t width, height;
int32_t refresh;
} mode;
};
struct shm_format {
struct wl_list link;
uint32_t format;
};
struct shm_info {
struct global_info global;
struct wl_shm *shm;
struct wl_list formats;
};
struct seat_info {
struct global_info global;
struct wl_seat *seat;
uint32_t capabilities;
};
struct weston_info {
struct wl_display *display;
int epoll_fd;
int timer_fd;
int display_fd;
uint32_t mask;
struct wl_list infos;
};
static void
print_global_info(void *data)
{
struct global_info *global = data;
printf("interface: '%s', version: %u, name: %u\n",
global->interface, global->version, global->id);
}
static void
init_global_info(struct weston_info *info,
struct global_info *global, uint32_t id,
const char *interface, uint32_t version)
{
global->id = id;
global->version = version;
global->interface = strdup(interface);
wl_list_insert(info->infos.prev, &global->link);
}
static void
print_output_info(void *data)
{
struct output_info *output = data;
const char *subpixel_orientation;
const char *transform;
print_global_info(data);
switch (output->geometry.subpixel) {
case WL_OUTPUT_SUBPIXEL_UNKNOWN:
subpixel_orientation = "unknown";
break;
case WL_OUTPUT_SUBPIXEL_NONE:
subpixel_orientation = "none";
break;
case WL_OUTPUT_SUBPIXEL_HORIZONTAL_RGB:
subpixel_orientation = "horizontal rgb";
break;
case WL_OUTPUT_SUBPIXEL_HORIZONTAL_BGR:
subpixel_orientation = "horizontal bgr";
break;
case WL_OUTPUT_SUBPIXEL_VERTICAL_RGB:
subpixel_orientation = "vertical rgb";
break;
case WL_OUTPUT_SUBPIXEL_VERTICAL_BGR:
subpixel_orientation = "vertical bgr";
break;
default:
fprintf(stderr, "unknown subpixel orientation %u\n",
output->geometry.subpixel);
subpixel_orientation = "unexpected value";
break;
}
switch (output->geometry.output_transform) {
case WL_OUTPUT_TRANSFORM_NORMAL:
transform = "normal";
break;
case WL_OUTPUT_TRANSFORM_90:
transform = "90°";
break;
case WL_OUTPUT_TRANSFORM_180:
transform = "180°";
break;
case WL_OUTPUT_TRANSFORM_270:
transform = "270°";
break;
case WL_OUTPUT_TRANSFORM_FLIPPED:
transform = "flipped";
break;
case WL_OUTPUT_TRANSFORM_FLIPPED_90:
transform = "flipped 90°";
break;
case WL_OUTPUT_TRANSFORM_FLIPPED_180:
transform = "flipped 180°";
break;
case WL_OUTPUT_TRANSFORM_FLIPPED_270:
transform = "flipped 270°";
break;
default:
fprintf(stderr, "unknown output transform %u\n",
output->geometry.output_transform);
transform = "unexpected value";
break;
}
printf("\tx: %d, y: %d, width: %d px, height %d px,\n",
output->geometry.x, output->geometry.y,
output->mode.width, output->mode.height);
printf("\tphysical_width: %d mm, physical_height: %d mm, refresh: %.f Hz,\n",
output->geometry.physical_width,
output->geometry.physical_height,
(float) output->mode.refresh / 1000);
printf("\tmake: '%s', model: '%s',\n",
output->geometry.make, output->geometry.model);
printf("\tsubpixel_orientation: %s, output_tranform: %s,\n",
subpixel_orientation, transform);
printf("\tflags:");
if (output->mode.flags & WL_OUTPUT_MODE_CURRENT)
printf(" current");
if (output->mode.flags & WL_OUTPUT_MODE_PREFERRED)
printf(" preferred");
printf("\n");
}
static void
print_shm_info(void *data)
{
struct shm_info *shm = data;
struct shm_format *format;
print_global_info(data);
printf("\tformats:");
wl_list_for_each(format, &shm->formats, link)
printf(" %s", (format->format == WL_SHM_FORMAT_ARGB8888) ?
"ARGB8888" : "XRGB8888");
printf("\n");
}
static void
print_seat_info(void *data)
{
struct seat_info *seat = data;
print_global_info(data);
printf("\tcapabilities:");
if (seat->capabilities & WL_SEAT_CAPABILITY_POINTER)
printf(" pointer");
if (seat->capabilities & WL_SEAT_CAPABILITY_KEYBOARD)
printf(" keyboard");
if (seat->capabilities & WL_SEAT_CAPABILITY_TOUCH)
printf(" touch");
printf("\n");
}
static void
seat_handle_capabilities(void *data, struct wl_seat *wl_seat,
enum wl_seat_capability caps)
{
struct seat_info *seat = data;
seat->capabilities = caps;
}
static const struct wl_seat_listener seat_listener = {
seat_handle_capabilities,
};
static void
add_seat_info(struct weston_info *info, uint32_t id, uint32_t version)
{
struct seat_info *seat = malloc(sizeof *seat);
init_global_info(info, &seat->global, id, "wl_seat", version);
seat->global.print = print_seat_info;
seat->seat = wl_display_bind(info->display, id, &wl_seat_interface);
wl_seat_add_listener(seat->seat, &seat_listener, seat);
}
static void
shm_handle_format(void *data, struct wl_shm *wl_shm, uint32_t format)
{
struct shm_info *shm = data;
struct shm_format *shm_format = malloc(sizeof *shm_format);
wl_list_insert(&shm->formats, &shm_format->link);
shm_format->format = format;
}
static const struct wl_shm_listener shm_listener = {
shm_handle_format,
};
static void
add_shm_info(struct weston_info *info, uint32_t id, uint32_t version)
{
struct shm_info *shm = malloc(sizeof *shm);
init_global_info(info, &shm->global, id, "wl_shm", version);
shm->global.print = print_shm_info;
wl_list_init(&shm->formats);
shm->shm = wl_display_bind(info->display, id, &wl_shm_interface);
wl_shm_add_listener(shm->shm, &shm_listener, shm);
}
static void
output_handle_geometry(void *data, struct wl_output *wl_output,
int32_t x, int32_t y,
int32_t physical_width, int32_t physical_height,
int32_t subpixel,
const char *make, const char *model,
int32_t output_transform)
{
struct output_info *output = data;
output->geometry.x = x;
output->geometry.y = y;
output->geometry.physical_width = physical_width;
output->geometry.physical_height = physical_height;
output->geometry.subpixel = subpixel;
output->geometry.make = strdup(make);
output->geometry.model = strdup(model);
output->geometry.output_transform = output_transform;
}
static void
output_handle_mode(void *data, struct wl_output *wl_output,
uint32_t flags, int32_t width, int32_t height,
int32_t refresh)
{
struct output_info *output = data;
output->mode.flags = flags;
output->mode.width = width;
output->mode.height = height;
output->mode.refresh = refresh;
}
static const struct wl_output_listener output_listener = {
output_handle_geometry,
output_handle_mode,
};
static void
add_output_info(struct weston_info *info, uint32_t id, uint32_t version)
{
struct output_info *output = malloc(sizeof *output);
init_global_info(info, &output->global, id, "wl_output", version);
output->global.print = print_output_info;
output->output = wl_display_bind(info->display, id,
&wl_output_interface);
wl_output_add_listener(output->output, &output_listener,
output);
}
static void
add_global_info(struct weston_info *info, uint32_t id,
const char *interface, uint32_t version)
{
struct global_info *global = malloc(sizeof *global);
init_global_info(info, global, id, interface, version);
global->print = print_global_info;
}
static void
global_handler(struct wl_display *display, uint32_t id,
const char *interface, uint32_t version, void *data)
{
struct weston_info *info = data;
if (!strcmp(interface, "wl_seat"))
add_seat_info(info, id, version);
else if (!strcmp(interface, "wl_shm"))
add_shm_info(info, id, version);
else if (!strcmp(interface, "wl_output"))
add_output_info(info, id, version);
else
add_global_info(info, id, interface, version);
}
static void
print_infos(struct wl_list *infos)
{
struct global_info *info;
wl_list_for_each(info, infos, link)
info->print(info);
}
static int
event_mask_update(uint32_t mask, void *data)
{
struct weston_info *info = data;
info->mask = mask;
return 0;
}
enum epoll_source_type {
TYPE_DISPLAY,
TYPE_TIMERFD
};
static void
main_loop(struct weston_info *info)
{
bool running;
struct epoll_event ep[16];
int i, count;
uint32_t tag;
running = true;
while (running) {
wl_display_flush(info->display);
count = epoll_wait(info->epoll_fd,
ep, ARRAY_LENGTH(ep), -1);
for (i = 0; i < count; i++) {
tag = ep[i].data.u32;
if (tag == TYPE_DISPLAY) {
wl_display_iterate(info->display,
info->mask);
} else if (tag == TYPE_TIMERFD) {
running = false;
} else {
fprintf(stderr, "unexpected fd type %u\n",
tag);
abort();
}
}
}
}
int
main(int argc, char **argv)
{
struct weston_info info;
struct epoll_event ep;
struct itimerspec spec;
info.display = wl_display_connect(NULL);
if (!info.display) {
fprintf(stderr, "failed to create display: %m\n");
return -1;
}
wl_list_init(&info.infos);
info.epoll_fd = os_epoll_create_cloexec();
info.display_fd = wl_display_get_fd(info.display, event_mask_update,
&info);
ep.events = EPOLLIN;
ep.data.u32 = TYPE_DISPLAY;
epoll_ctl(info.epoll_fd, EPOLL_CTL_ADD, info.display_fd, &ep);
info.timer_fd = timerfd_create(CLOCK_REALTIME, 0);
if (info.timer_fd < 0) {
fprintf(stderr, "failed to create timer fd: %m\n");
return -1;
}
ep.events = EPOLLIN;
ep.data.u32 = TYPE_TIMERFD;
epoll_ctl(info.epoll_fd, EPOLL_CTL_ADD, info.timer_fd, &ep);
wl_display_add_global_listener(info.display,
global_handler,
&info);
spec.it_interval.tv_sec = 0;
spec.it_interval.tv_nsec = 0;
spec.it_value.tv_sec = 0;
spec.it_value.tv_nsec = 200 * 1000 * 1000;
timerfd_settime(info.timer_fd, 0, &spec, NULL);
main_loop(&info);
print_infos(&info.infos);
return 0;
}

@ -163,6 +163,7 @@ if test x$enable_clients = xyes; then
AC_DEFINE([BUILD_CLIENTS], [1], [Build the Wayland clients])
PKG_CHECK_MODULES(CLIENT, [wayland-client wayland-egl egl >= 7.10 cairo >= 1.10.0 xkbcommon wayland-cursor])
PKG_CHECK_MODULES(WESTON_INFO, [wayland-client])
CLIENT_CFLAGS="$CLIENT_CFLAGS $IMAGE_CFLAGS"
CLIENT_LIBS="$CLIENT_LIBS $IMAGE_LIBS"

Loading…
Cancel
Save