commit 2515f03
Michael Forney
·
2014-08-06 01:52:07 +0000 UTC
parent 625eb82
xwm: Implement close
2 files changed,
+65,
-6
+2,
-1
1@@ -72,7 +72,8 @@ $(dir)_CFLAGS += -DENABLE_XWAYLAND
2 $(dir)_PACKAGES += \
3 xcb \
4 xcb-composite \
5- xcb-ewmh
6+ xcb-ewmh \
7+ xcb-icccm
8
9 SWC_SOURCES += \
10 libswc/xserver.c \
+63,
-5
1@@ -40,7 +40,7 @@ struct xwl_window
2 {
3 xcb_window_t id;
4 uint32_t surface_id;
5- bool override_redirect;
6+ bool override_redirect, supports_delete;
7 struct wl_list link;
8
9 /* Only used for paired windows. */
10@@ -52,8 +52,10 @@ struct xwl_window
11
12 enum atom
13 {
14- ATOM_WM_S0,
15 ATOM_WL_SURFACE_ID,
16+ ATOM_WM_DELETE_WINDOW,
17+ ATOM_WM_PROTOCOLS,
18+ ATOM_WM_S0,
19 };
20
21 static struct
22@@ -70,11 +72,13 @@ static struct
23 const char * name;
24 xcb_intern_atom_cookie_t cookie;
25 xcb_atom_t value;
26- } atoms[2];
27+ } atoms[4];
28 } xwm = {
29 .atoms = {
30- [ATOM_WM_S0] = "WM_S0",
31- [ATOM_WL_SURFACE_ID] = "WL_SURFACE_ID",
32+ [ATOM_WL_SURFACE_ID] = "WL_SURFACE_ID",
33+ [ATOM_WM_DELETE_WINDOW] = "WM_DELETE_WINDOW",
34+ [ATOM_WM_PROTOCOLS] = "WM_PROTOCOLS",
35+ [ATOM_WM_S0] = "WM_S0",
36 }
37 };
38
39@@ -97,6 +101,29 @@ static void update_name(struct xwl_window * xwl_window)
40 window_set_title(&xwl_window->window, NULL, 0);
41 }
42
43+static void update_protocols(struct xwl_window * xwl_window)
44+{
45+ xcb_get_property_cookie_t cookie;
46+ xcb_icccm_get_wm_protocols_reply_t reply;
47+ unsigned index;
48+
49+ cookie = xcb_icccm_get_wm_protocols(xwm.connection, xwl_window->id,
50+ xwm.atoms[ATOM_WM_PROTOCOLS].value);
51+
52+ xwl_window->supports_delete = true;
53+
54+ if (!xcb_icccm_get_wm_protocols_reply(xwm.connection, cookie, &reply, NULL))
55+ return;
56+
57+ for (index = 0; index < reply.atoms_len; ++index)
58+ {
59+ if (reply.atoms[index] == xwm.atoms[ATOM_WM_DELETE_WINDOW].value)
60+ xwl_window->supports_delete = true;
61+ }
62+
63+ xcb_icccm_get_wm_protocols_reply_wipe(&reply);
64+}
65+
66 static struct xwl_window * find_window(struct wl_list * list, xcb_window_t id)
67 {
68 struct xwl_window * window;
69@@ -170,10 +197,38 @@ static void unfocus(struct window * window)
70 }
71 }
72
73+static void close(struct window * window)
74+{
75+ struct xwl_window * xwl_window
76+ = wl_container_of(window, xwl_window, window);
77+
78+ if (xwl_window->supports_delete)
79+ {
80+ xcb_client_message_event_t event = {
81+ .response_type = XCB_CLIENT_MESSAGE,
82+ .format = 32,
83+ .window = xwl_window->id,
84+ .type = xwm.atoms[ATOM_WM_PROTOCOLS].value,
85+ .data.data32 = {
86+ xwm.atoms[ATOM_WM_DELETE_WINDOW].value,
87+ XCB_CURRENT_TIME,
88+ },
89+ };
90+
91+ xcb_send_event(xwm.connection, false, xwl_window->id,
92+ XCB_EVENT_MASK_NO_EVENT, (const char *) &event);
93+ }
94+ else
95+ xcb_kill_client(xwm.connection, xwl_window->id);
96+
97+ xcb_flush(xwm.connection);
98+}
99+
100 static const struct window_impl xwl_window_handler = {
101 .configure = &configure,
102 .focus = &focus,
103 .unfocus = &unfocus,
104+ .close = &close,
105 };
106
107 static void handle_surface_destroy(struct wl_listener * listener, void * data)
108@@ -232,6 +287,7 @@ static bool manage_window(struct xwl_window * xwl_window)
109 values[0] = 0;
110 xcb_configure_window(xwm.connection, xwl_window->id, mask, values);
111 update_name(xwl_window);
112+ update_protocols(xwl_window);
113
114 window_set_state(&xwl_window->window, SWC_WINDOW_STATE_NORMAL);
115 }
116@@ -311,6 +367,8 @@ static void property_notify(xcb_property_notify_event_t * event)
117 {
118 update_name(xwl_window);
119 }
120+ else if (event->atom == xwm.atoms[ATOM_WM_PROTOCOLS].value)
121+ update_protocols(xwl_window);
122 }
123
124 static void client_message(xcb_client_message_event_t * event)