使用XCB编写X Window程序(三) 捕获并响应事件(Event)2015-05-13GUI程序都是事件驱动的,目前这已经是大家的共识,X Window也不例外。在这一篇中,将展示X核心协议中有哪些事件,以及怎么使用XCB来捕获并响应事件。首先还是先给出一份完整的代码及其运行效果,然后再做详细的解释。代码如下:
1 #include <stdlib.h>
2 #include <stdio.h>
3 #include <inttypes.h>
4
5 #include <xcb/xcb.h>
6
7 /* print names of modifiers present in mask */
8 void
9 print_modifiers (uint32_t mask)
10 {
11 const char *MODIFIERS[] = {
12 "Shift", "Lock", "Ctrl", "Alt",
13 "Mod2", "Mod3", "Mod4", "Mod5",
14 "Button1", "Button2", "Button3", "Button4", "Button5"
15 };
16
17 printf ("Modifier mask: ");
18 for (const char **modifier = MODIFIERS ; mask; mask >>= 1, ++modifier) {
19 if (mask & 1) {
20 printf (*modifier);
21 }
22 }
23 printf ("
");
24 }
25
26 int
27 main ()
28 {
29 /* Open the connection to the X server */
30 xcb_connection_t *connection = xcb_connect (NULL, NULL);
31
32 /* Get the first screen */
33 xcb_screen_t *screen = xcb_setup_roots_iterator (xcb_get_setup (connection)).data;
34
35
36 /* Create the window */
37 xcb_window_t window= xcb_generate_id (connection);
38
39 uint32_t mask= XCB_CW_BACK_PIXEL | XCB_CW_EVENT_MASK;
40 uint32_t values[2] = {screen->white_pixel,
41 XCB_EVENT_MASK_EXPOSURE | XCB_EVENT_MASK_BUTTON_PRESS |
42 XCB_EVENT_MASK_BUTTON_RELEASE | XCB_EVENT_MASK_POINTER_MOTION |
43 XCB_EVENT_MASK_ENTER_WINDOW | XCB_EVENT_MASK_LEAVE_WINDOW |
44 XCB_EVENT_MASK_KEY_PRESS| XCB_EVENT_MASK_KEY_RELEASE };
45
46 xcb_create_window (connection,
470, /* depth */
48window,
49screen->root,/* parent window */
500, 0,/* x, y*/
51600, 400,/* width, height */
5210,/* border_width*/
53XCB_WINDOW_CLASS_INPUT_OUTPUT, /* class */
54screen->root_visual, /* visual*/
55mask, values );/* masks */
56
57 /* Map the window on the screen */
58 xcb_map_window (connection, window);
59
60 xcb_flush (connection);
61
62 xcb_generic_event_t *event;
63 while ( (event = xcb_wait_for_event (connection)) ) {
64 switch (event->response_type & ~0x80) {
65 case XCB_EXPOSE: {
66 xcb_expose_event_t *expose = (xcb_expose_event_t *)event;
67
68 printf ("Window %"PRIu32" exposed. Region to be redrawn at location (%"PRIu16",%"PRIu16"), with dimension (%"PRIu16",%"PRIu16")
",
69 expose->window, expose->x, expose->y, expose->width, expose->height );
70 break;
71 }
72 case XCB_BUTTON_PRESS: {
73 xcb_button_press_event_t *bp = (xcb_button_press_event_t *)event;
74 print_modifiers (bp->state);
75
76 switch (bp->detail) {
77 case 4:
78 printf ("Wheel Button up in window %"PRIu32", at coordinates (%"PRIi16",%"PRIi16")
",
79 bp->event, bp->event_x, bp->event_y );
80 break;
81 case 5:
82 printf ("Wheel Button down in window %"PRIu32", at coordinates (%"PRIi16",%"PRIi16")
",
83 bp->event, bp->event_x, bp->event_y );
84 break;
85 default:
86 printf ("Button %"PRIu8" pressed in window %"PRIu32", at coordinates (%"PRIi16",%"PRIi16")
",
87 bp->detail, bp->event, bp->event_x, bp->event_y );
88 break;
89 }
90 break;
91 }
92 case XCB_BUTTON_RELEASE: {
93 xcb_button_release_event_t *br = (xcb_button_release_event_t *)event;
94 print_modifiers(br->state);
95
96 printf ("Button %"PRIu8" released in window %"PRIu32", at coordinates (%"PRIi16",%"PRIi16")
",
97 br->detail, br->event, br->event_x, br->event_y );
98 break;
99 }
100 case XCB_MOTION_NOTIFY: {
101 xcb_motion_notify_event_t *motion = (xcb_motion_notify_event_t *)event;
102
103 printf ("Mouse moved in window %"PRIu32", at coordinates (%"PRIi16",%"PRIi16")
",
104 motion->event, motion->event_x, motion->event_y );
105 break;
106 }
107 case XCB_ENTER_NOTIFY: {
108 xcb_enter_notify_event_t *enter = (xcb_enter_notify_event_t *)event;
109
110 printf ("Mouse entered window %"PRIu32", at coordinates (%"PRIi16",%"PRIi16")
",
111 enter->event, enter->event_x, enter->event_y );
112 break;
113 }
114 case XCB_LEAVE_NOTIFY: {
115 xcb_leave_notify_event_t *leave = (xcb_leave_notify_event_t *)event;
116
117 printf ("Mouse left window %"PRIu32", at coordinates (%"PRIi16",%"PRIi16")
",
118 leave->event, leave->event_x, leave->event_y );
119 break;
120 }
121 case XCB_KEY_PRESS: {
122 xcb_key_press_event_t *kp = (xcb_key_press_event_t *)event;
123 print_modifiers(kp->state);
124
125 printf ("Key pressed in window %"PRIu32"
",
126 kp->event);
127 break;
128 }
129 case XCB_KEY_RELEASE: {
130 xcb_key_release_event_t *kr = (xcb_key_release_event_t *)event;
131 print_modifiers(kr->state);
132
133 printf ("Key released in window %"PRIu32"
",
134 kr->event);
135 break;
136 }
137 default:
138 /* Unknown event type, ignore it */
139 printf ("Unknown event: %"PRIu8"
",
140 event->response_type);
141 break;
142 }
143
144 free (event);
145 }
146
147 return 0;
148 }