- c - 在位数组中找到第一个零
- linux - Unix 显示有关匹配两种模式之一的文件的信息
- 正则表达式替换多个文件
- linux - 隐藏来自 xtrace 的命令
我想了解 Linux 桌面环境如何与 Xserver 一起工作。我读到大多数窗口管理器不直接打开套接字,而是使用 Xlib 绑定(bind) WM 正在编写的任何语言,或者您可以使用更高级别的绑定(bind) XCB;但我想知道直接向 Xserver 打开套接字有什么好处?
最佳答案
我不会告诉你优点,但我会告诉你怎么做。
前段时间我找到了这个人的一个例子,现在找不到了,但这里或多或少是他的代码。了解 XCB 等客户端库的幕后情况非常有趣。
为了向 X 服务器发送请求,您需要:
打开套接字、创建图形上下文、创建窗口和映射窗口的 API 类似于:
x11_connection_t connection = {0};
x11_init_connection(&connection);
x11_state_t state;
state.socket_fd = connection.socket_fd;
state.id_base = connection.setup->id_base;
state.root_window = connection.root[0].window_id;
state.root_visual = connection.root[0].visual_id;
state.root_depth = connection.root[0].depth;
state.gcontext = x11_init_gc(&state, X11_GC_GRAPHICS_EXPOSURES, (u32[]){X11_EXPOSURES_NOT_ALLOWED});
state.window = x11_init_window(&state, 0,0, WIDTH,HEIGHT, state.root_window, state.root_visual,
X11_CW_BACK_PIXEL | X11_CW_EVENT_MASK,
(u32[]){XCB_RGB_BLUE, X11_EVENT_MASK_KEY_PRESS | X11_EVENT_MASK_POINTER_MOTION}); // X11_EVENT_MASK_KEY_PRESS | X11_EVENT_MASK_POINTER_MOTION | X11_EVENT_MASK_STRUCTURE_NOTIFY | X11_EVENT_MASK_EXPOSURE
x11_map_window(&state, state.window);
但首先我们需要实现它。
为了说明,这里是前 13 个 X 协议(protocol)操作码:
#define X11_OPCODE_CREATE_WINDOW 1
#define X11_OPCODE_CHANGE_WINDOW_ATTRIBUTES 2
#define X11_OPCODE_GET_WINDOW_ATTRIBUTES 3
#define X11_OPCODE_DESTROY_WINDOW 4
#define X11_OPCODE_DESTROY_SUBWINDOWS 5
#define X11_OPCODE_CHANGE_SAVE_SET 6
#define X11_OPCODE_REPARENT_WINDOW 7
#define X11_OPCODE_MAP_WINDOW 8
#define X11_OPCODE_MAP_SUBWINDOWS 9
#define X11_OPCODE_UNMAP_WINDOW 10
#define X11_OPCODE_UNMAP_SUBWINDOWS 11
#define X11_OPCODE_CONFIGURE_WINDOW 12
#define X11_OPCODE_CIRCULATE_WINDOW 13
您可以使用如下函数打开套接字,
int x11_init_socket(){
int socket_fd = socket(AF_UNIX, SOCK_STREAM, 0); // Create the socket!
struct sockaddr_un serv_addr = {0};
serv_addr.sun_family = AF_UNIX;
strcpy(serv_addr.sun_path, "/tmp/.X11-unix/X0");
int srv_len = sizeof(struct sockaddr_un);
connect(socket_fd, (struct sockaddr*)&serv_addr, sizeof(serv_addr));
return socket_fd;
}
然后你需要握手,
int x11_init_connection(x11_connection_t* connection){
connection->socket_fd = x11_init_socket();
x11_connection_request_t request = {0};
request.order = 'l'; // Little endian!
request.major = 11;
request.minor = 0; // Version 11.0
write(connection->socket_fd, &request, sizeof(x11_connection_request_t)); // Send request
read(connection->socket_fd, &connection->header, sizeof(x11_connection_reply_t)); // Read reply header
if(connection->header.success == 0) return connection->header.success; // Error handling!
connection->setup = sbrk(connection->header.length * 4); // Allocate memory for remainder of data
read(connection->socket_fd, connection->setup, connection->header.length * 4); // Read remainder of data
void* p = ((void*)connection->setup);
p += sizeof(x11_connection_setup_t) + connection->setup->vendor_length; // Ignore the vendor
connection->format = p; p += sizeof(x11_pixmap_format_t) * connection->setup->formats; // Align struct with format sections. Move pointer to end of section
connection->root = p; p += sizeof(x11_root_t) * connection->setup->roots; // Align struct with root section(s). Move pointer to end of section
connection->depth = p; p += sizeof(x11_depth_t); // Align depth struct with first depth section. Move pointer to end of section
connection->visual = p; // Align visual with first visual for first depth
return connection->header.success;
}
以及X服务器喜欢的一堆数据结构:
typedef struct{
u8 order;
u8 pad1;
u16 major, minor;
u16 auth_proto, auth_data;
u16 pad2;
}x11_connection_request_t;
typedef struct{
u8 success;
u8 pad1;
u16 major, minor;
u16 length;
}x11_connection_reply_t;
typedef struct{
u32 release;
u32 id_base, id_mask;
u32 motion_buffer_size;
u16 vendor_length;
u16 request_max;
u8 roots;
u8 formats;
u8 image_order;
u8 bitmap_order;
u8 scanline_unit, scanline_pad;
u8 keycode_min, keycode_max;
u32 pad;
}x11_connection_setup_t;
typedef struct{
u8 depth;
u8 bpp;
u8 scanline_pad;
u8 pad1;
u32 pad2;
}x11_pixmap_format_t;
typedef struct{
u32 window_id;
u32 colormap;
u32 white, black;
u32 input_mask;
u16 width, height;
u16 width_mm, height_mm;
u16 maps_min, maps_max;
u32 visual_id;
u8 backing_store;
u8 save_unders;
u8 depth;
u8 depths;
}x11_root_t;
typedef struct{
u8 depth;
u8 pad1;
u16 visuals;
u32 pad2;
}x11_depth_t;
typedef struct{
u8 group;
u8 bits;
u16 colormap_entries;
u32 mask_red, mask_green, mask_blue;
u32 pad;
}x11_visual_t;
typedef struct{
u8 response_type; /**< Type of the response */
u8 pad0; /**< Padding */
u16 sequence; /**< Sequence number */
u32 pad[7]; /**< Padding */
u32 full_sequence; /**< full sequence */
}x11_generic_event_t;
typedef struct{
u8 success;
u8 code;
u16 seq;
u32 id;
u16 op_major;
u8 op_minor;
u8 pad[21];
}x11_error_t;
typedef struct{
int socket_fd;
x11_connection_reply_t header;
x11_connection_setup_t* setup;
x11_pixmap_format_t* format;
x11_root_t* root;
x11_depth_t* depth;
x11_visual_t* visual;
}x11_connection_t;
typedef struct{
int socket_fd;
u32 id_base; // We'll use this to generate 32-bit identifiers!
u32 root_window;
u32 root_visual;
u8 root_depth;
u32 window;
u32 gcontext;
}x11_state_t;
您还需要一个函数来生成 32 位标识符:
u32 x11_generate_id(x11_connection_t* connection){
static u32 id = 0;
return (id++ | connection->setup->id_base);
}
最后,您需要将数据包与请求组合在一起的实际函数。以下是用于发送 X11_OPCODE_CREATE_GC
、X11_OPCODE_CREATE_WINDOW
、X11_OPCODE_MAP_WINDOW
和 X11_OPCODE_PUT_IMAGE
的辅助函数。
#define X11_NONE 0x00000000L // X11_NONE is the universal null resource or null atom parameter value for many core X requests
#define X11_COPY_FROM_PARENT 0x00000000L // X11_COPY_FROM_PARENT can be used for many xcb_create_window parameters
#define X11_CURRENT_TIME 0x00000000L // X11_CURRENT_TIME can be used in most requests that take an xcb_timestamp_t
#define X11_NO_SYMBOL 0x00000000L // X11_NO_SYMBOL fills in unused entries in xcb_keysym_t tables
enum x11_exposures_t{
X11_EXPOSURES_NOT_ALLOWED = 0,
X11_EXPOSURES_ALLOWED = 1,
X11_EXPOSURES_DEFAULT = 2
};
enum x11_gc_t{
X11_GC_FUNCTION = 1<<0,
X11_GC_PLANE_MASK = 1<<1,
X11_GC_FOREGROUND = 1<<2,
X11_GC_BACKGROUND = 1<<3,
X11_GC_LINE_WIDTH = 1<<4,
X11_GC_LINE_STYLE = 1<<5,
X11_GC_CAP_STYLE = 1<<6,
X11_GC_JOIN_STYLE = 1<<7,
X11_GC_FILL_STYLE = 1<<8,
X11_GC_FILL_RULE = 1<<9,
X11_GC_TILE = 1<<10,
X11_GC_STIPPLE = 1<<11,
X11_GC_TILE_STIPPLE_ORIGIN_X = 1<<12,
X11_GC_TILE_STIPPLE_ORIGIN_Y = 1<<13,
X11_GC_FONT = 1<<14,
X11_GC_SUBWINDOW_MODE = 1<<15,
X11_GC_GRAPHICS_EXPOSURES = 1<<16,
X11_GC_CLIP_ORIGIN_X = 1<<17,
X11_GC_CLIP_ORIGIN_Y = 1<<18,
X11_GC_CLIP_MASK = 1<<19,
X11_GC_DASH_OFFSET = 1<<20,
X11_GC_DASH_LIST = 1<<21,
X11_GC_ARC_MODE = 1<<22,
};
u32 x11_init_gc(x11_state_t* state, u32 value_mask, u32* value_list){
u32 gcontext_id = x11_generate_id(state);
u16 flag_count = popcnt(value_mask);
u16 length = 4 + flag_count;
u32* packet = sbrk(length * 4);
packet[0] = X11_OPCODE_CREATE_GC | (length<<16); // The first `u32` in the packet is always the opcode and the length of the packet!
packet[1] = gcontext_id;
packet[2] = state->root_window;
packet[3] = value_mask;
for(int i=0; i < flag_count; ++i)
packet[4 + i] = value_list[i];
write(state->socket_fd, packet, length * 4);
sbrk(-(length * 4));
return gcontext_id;
}
enum x11_cw_t{
X11_CW_BACK_PIXMAP = 1<<0,
X11_CW_BACK_PIXEL = 1<<1,
X11_CW_BORDER_PIXMAP = 1<<2,
X11_CW_BORDER_PIXEL = 1<<3,
X11_CW_BIT_GRAVITY = 1<<4,
X11_CW_WIN_GRAVITY = 1<<5,
X11_CW_BACKING_STORE = 1<<6,
X11_CW_BACKING_PLANES = 1<<7,
X11_CW_BACKING_PIXEL = 1<<8,
X11_CW_OVERRIDE_REDIRECT = 1<<9,
X11_CW_SAVE_UNDER = 1<<10,
X11_CW_EVENT_MASK = 1<<11,
X11_CW_DONT_PROPAGATE = 1<<12,
X11_CW_COLORMAP = 1<<13,
X11_CW_CURSOR = 1<<14
};
enum x11_event_mask_t{
X11_EVENT_MASK_NO_EVENT = 0,
X11_EVENT_MASK_KEY_PRESS = 1<<0, // 0x00000001
X11_EVENT_MASK_KEY_RELEASE = 1<<1, // 0x00000002
X11_EVENT_MASK_BUTTON_PRESS = 1<<2, // 0x00000004
X11_EVENT_MASK_BUTTON_RELEASE = 1<<3, // 0x00000008
X11_EVENT_MASK_ENTER_WINDOW = 1<<4, // 0x00000010
X11_EVENT_MASK_LEAVE_WINDOW = 1<<5, // 0x00000020
X11_EVENT_MASK_POINTER_MOTION = 1<<6, // 0x00000040
X11_EVENT_MASK_POINTER_MOTION_HINT = 1<<7, // 0x00000080
X11_EVENT_MASK_BUTTON_1_MOTION = 1<<8, // 0x00000100
X11_EVENT_MASK_BUTTON_2_MOTION = 1<<9, // 0x00000200
X11_EVENT_MASK_BUTTON_3_MOTION = 1<<10, // 0x00000400
X11_EVENT_MASK_BUTTON_4_MOTION = 1<<11, // 0x00000800
X11_EVENT_MASK_BUTTON_5_MOTION = 1<<12, // 0x00001000
X11_EVENT_MASK_BUTTON_MOTION = 1<<13, // 0x00002000
X11_EVENT_MASK_KEYMAP_STATE = 1<<14, // 0x00004000
X11_EVENT_MASK_EXPOSURE = 1<<15, // 0x00008000
X11_EVENT_MASK_VISIBILITY_CHANGE = 1<<16, // 0x00010000
X11_EVENT_MASK_STRUCTURE_NOTIFY = 1<<17, // 0x00020000
X11_EVENT_MASK_RESIZE_REDIRECT = 1<<18, // 0x00040000
X11_EVENT_MASK_SUBSTRUCTURE_NOTIFY = 1<<19, // 0x00080000
X11_EVENT_MASK_SUBSTRUCTURE_REDIRECT = 1<<20, // 0x00100000
X11_EVENT_MASK_FOCUS_CHANGE = 1<<21, // 0x00200000
X11_EVENT_MASK_PROPERTY_CHANGE = 1<<22, // 0x00400000
X11_EVENT_MASK_COLOR_MAP_CHANGE = 1<<23, // 0x00800000
X11_EVENT_MASK_OWNER_GRAB_BUTTON = 1<<24 // 0x01000000
};
#define X11_DEFAULT_BORDER 0
#define X11_DEFAULT_GROUP 0
u32 x11_init_window(x11_state_t* state, u16 x, u16 y, u16 w, u16 h, u32 window_parent, u32 visual, u32 value_mask, u32* value_list){
u32 window_id = x11_generate_id(state);
u16 flag_count = popcnt(value_mask);
u16 length = 8 + flag_count;
u32* packet = sbrk(length * 4);
packet[0] = X11_OPCODE_CREATE_WINDOW | length<<16; // The first `u32` in the packet is always the opcode and the length of the packet!
packet[1] = window_id;
packet[2] = window_parent;
packet[3] = x | (y<<16);
packet[4] = w | (h<<16);
packet[5] = (X11_DEFAULT_BORDER<<16) | X11_DEFAULT_GROUP;
packet[6] = visual;
packet[7] = value_mask;
for(int i=0;i < flag_count; ++i)
packet[8 + i] = value_list[i];
write(state->socket_fd, packet, length * 4);
sbrk(-(length * 4));
return window_id;
}
void x11_map_window(x11_state_t* state, u32 window_id){
int const length = 2;
u32 packet[length];
packet[0] = X11_OPCODE_MAP_WINDOW | (length<<16); // The first `u32` in the packet is always the opcode and the length of the packet!
packet[1] = window_id;
write(state->socket_fd, packet, 8);
}
enum x11_image_format_t{
X11_IMAGE_FORMAT_XY_BITMAP = 0,
X11_IMAGE_FORMAT_XY_PIXMAP = 1,
X11_IMAGE_FORMAT_Z_PIXMAP = 2
};
void x11_put_img(x11_state_t* state, u16 x, u16 y, u32* data){
u32 packet[6];
u16 const length = ((state->tile_width * state->tile_height)) + 6;
packet[0] = X11_OPCODE_PUT_IMAGE | (X11_IMAGE_FORMAT_Z_PIXMAP<<8) | (length<<16); // The first `u32` in the packet is always the opcode and the length of the packet!
packet[1] = state->window;
packet[2] = state->gcontext;
packet[3] = state->tile_width | (state->tile_height<<16);
packet[4] = x | (y<<16);
packet[5] = state->root_depth<<8;
write(state->socket_fd, packet, 24);
write(state->socket_fd, data, state->tile_width * state->tile_height * 4);
}
关于linux - 直接打开到 Xserver 的套接字,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/12111861/
我想在 Cent OS 机器服务器上运行 unoconv 显然没有任何 GUI。 Unoconv 使用带有 -headless 参数的 OpenOffice,但它也不起作用。 我收到以下错误: /us
我对 XCreateGC 函数性能有疑问。似乎在某些情况下工作正常(快速),而在其他情况下则非常慢:)。有关更多详细信息,请查看此代码: void some_function(int dx, int
我正在努力在 Centos 7.2 服务器上设置桌面环境。我通过以下方式连接到服务器:- 虽然腻子 ssh 到我的用户的跳转框然后从跳转框 使用我的 ID SSH 到 Centos 7.2 服务器 我
我正在开发一个运行单个 GUI 应用程序的嵌入式系统。我正在使用自定义 Linux 构建 (buildroot),并且没有安装窗口系统。应用程序使用 EGL 分配屏幕渲染缓冲区。 我已经开始致力于支持
我正在系统资源有限的嵌入式 linux 平台上工作。 我想通过简单的转换(例如滑入滑出、淡入淡出)进行全屏幻灯片放映。 我尝试了 PyGtk+GTK+Cairo,但它非常慢,当我为 GTK 图像控件设
我创建了一个 Dockerfile,用于安装 Xvfb 和 firefox 以及所需的所有依赖项,并且我能够使用在 Xserver 的 DISPLAY=:1 上启动的 firefox 创建一个容器。
我想了解 Linux 桌面环境如何与 Xserver 一起工作。我读到大多数窗口管理器不直接打开套接字,而是使用 Xlib 绑定(bind) WM 正在编写的任何语言,或者您可以使用更高级别的绑定
我在 Docker 容器内运行的应用程序使用 OpenGL 进行离屏渲染。 如果容器运行在有图形环境的宿主机上,它应该使用宿主机的XServer进行渲染。 我设置了这样的容器,它在任何安装了 mesa
我想在以用户身份登录 bash 后运行 Emacs。但我也希望能够在按下 CTRL-Z 时跳回 bash 提示符。 我尝试了一些 .bashrc 和 .profile 的设置: emacs eval
我正在开发一个用于自动生成报告的小项目,我正在开发一些 HTML,我使用 wkhtmltopdf 将其转换为 pdf。 我使用 windows 版本开发了一个解决方案,但在迁移到 Linux 时遇到了
我在我的容器中安装了最小的 Ubuntu,我想运行 Xserver。我需要 XServer,因为我的应用程序需要 meshlabserver,它本身需要 Xserver。 我安装了 xserver-x
我想编写一个原始的、独立于 DE 的应用程序。因此我想独立于 Qt 和 GTK。 Qt/GTK 下面的下一个库是什么。我的意思是,它们中的任何一个都使用并且在每个 图形 linux 系统上可用的最小公
我正在设置一些新的 VNC 服务器。我已经将这个设置与 CentOS 6.3 一起使用,尽管我不确定这种差异是否是真正的问题。 我提供的窗口管理器之一是fluxbox,但是当我启动它时,我总是得到以下
我使用 Xming 在 Windows 机器上运行 Xserver,它工作得很好。 export DISPLAY=:0.0 但我想将显示导出到另一台 linux 主机上。 export DISPLAY
我正在尝试使用 putty 和 XMing 从我的 Fedora 20 运行程序。我以前在其他机器上使用过这个配置,我能够在 Linux 上运行 GUI 程序并在我的 Windows 7 中显示它们。
我是 python 新手,正在尝试探索图形,您能否帮助我了解我是否可以在没有运行 XSERVER 的 Linux 系统上使用 matplotlib 在控制台上绘制图形? 谢谢。 最佳答案 您可以在没有
我在 Windows 7 桌面上使用 Mobaxterm(免费版)连接到 AWS 上的 SUSE 11 Enterprise 服务器。我试图在我的 xtrem 客户端上显示 xclock 程序,但我收
我正在尝试使用 NVIDIA GPU 为 OpenGL headless (headless)应用程序创建运行 X 服务器的 Docker 镜像。 (可用于创建纹理、在无屏幕的情况下运行 Unity3
我有一个将 WebRenderer 用于 java headless 浏览器的 Java 应用程序。 WebRenderer 不需要 xserver 来运行,我已经通过卸载所有 x11 库和 xser
我需要一些关于如何将数据从 Python 脚本发送到 Web 浏览器的想法。脚本(和浏览器)在 Linux(Raspberry Pi 上的 Raspbian)的 xServer 环境下运行。 Pyth
我是一名优秀的程序员,十分优秀!