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)