Browse Source

Add support for motif wm hints

This makes motif wm hints available on clients as c.motif_wm_hints.
Actually interpreting all the values is up to Lua. The definition of the
necessary properties is taken from motif.

Signed-off-by: Uli Schlachter <psychon@znc.in>
Uli Schlachter 1 year ago
parent
commit
d76143f97b
5 changed files with 212 additions and 0 deletions
  1. 1
    0
      common/atoms.list
  2. 126
    0
      objects/client.c
  3. 45
    0
      objects/client.h
  4. 39
    0
      property.c
  5. 1
    0
      property.h

+ 1
- 0
common/atoms.list View File

@@ -64,3 +64,4 @@ XSEL_DATA
64 64
 WM_TAKE_FOCUS
65 65
 AWESOME_CLIENT_ORDER
66 66
 _XKB_RULES_NAMES
67
+_MOTIF_WM_HINTS

+ 126
- 0
objects/client.c View File

@@ -646,6 +646,43 @@
646 646
  * @see size_hints_honor
647 647
  */
648 648
 
649
+/**
650
+ * The motif WM hints of the client.
651
+ *
652
+ * This is nil if the client has no motif hints. Otherwise, this is a table that
653
+ * contains the present properties. Note that awesome provides these properties
654
+ * as-is and does not interpret them for you. For example, if the function table
655
+ * only has "resize" set to true, this means that the window requests to be only
656
+ * resizable, but asks for the other functions not to be able. If however both
657
+ * "resize" and "all" are set, this means that all but the resize function
658
+ * should be enabled.
659
+ *
660
+ * **Signal:**
661
+ *
662
+ *  * *property::motif\_wm\_hints*
663
+ *
664
+ * @property motif_wm_hints
665
+ * @param table
666
+ * @tfield[opt] table table.functions
667
+ * @tfield[opt] boolean table.functions.all
668
+ * @tfield[opt] boolean table.functions.resize
669
+ * @tfield[opt] boolean table.functions.move
670
+ * @tfield[opt] boolean table.functions.minimize
671
+ * @tfield[opt] boolean table.functions.maximize
672
+ * @tfield[opt] boolean table.functions.close
673
+ * @tfield[opt] table table.decorations
674
+ * @tfield[opt] boolean table.decorations.all
675
+ * @tfield[opt] boolean table.decorations.border
676
+ * @tfield[opt] boolean table.decorations.resizeh
677
+ * @tfield[opt] boolean table.decorations.title
678
+ * @tfield[opt] boolean table.decorations.menu
679
+ * @tfield[opt] boolean table.decorations.minimize
680
+ * @tfield[opt] boolean table.decorations.maximize
681
+ * @tfield[opt] string table.input_mode
682
+ * @tfield[opt] table table.status
683
+ * @tfield[opt] boolean table.status.tearoff_window
684
+ */
685
+
649 686
 /**
650 687
  * Set the client sticky, i.e. available on all tags.
651 688
  *
@@ -978,6 +1015,17 @@ DO_CLIENT_SET_STRING_PROPERTY(role)
978 1015
 DO_CLIENT_SET_STRING_PROPERTY(machine)
979 1016
 #undef DO_CLIENT_SET_STRING_PROPERTY
980 1017
 
1018
+void
1019
+client_set_motif_wm_hints(lua_State *L, int cidx, motif_wm_hints_t hints)
1020
+{
1021
+    client_t *c = luaA_checkudata(L, cidx, &client_class);
1022
+    if (memcmp(&c->motif_wm_hints, &hints, sizeof(c->motif_wm_hints)) == 0)
1023
+        return;
1024
+
1025
+    memcpy(&c->motif_wm_hints, &hints, sizeof(c->motif_wm_hints));
1026
+    luaA_object_emit_signal(L, cidx, "property::motif_wm_hints", 0);
1027
+}
1028
+
981 1029
 void
982 1030
 client_find_transient_for(client_t *c)
983 1031
 {
@@ -1416,6 +1464,7 @@ client_update_properties(lua_State *L, int cidx, client_t *c)
1416 1464
     xcb_get_property_cookie_t net_wm_icon_name  = property_get_net_wm_icon_name(c);
1417 1465
     xcb_get_property_cookie_t wm_class          = property_get_wm_class(c);
1418 1466
     xcb_get_property_cookie_t wm_protocols      = property_get_wm_protocols(c);
1467
+    xcb_get_property_cookie_t motif_wm_hints    = property_get_motif_wm_hints(c);
1419 1468
     xcb_get_property_cookie_t opacity           = xwindow_get_opacity_unchecked(c->window);
1420 1469
 
1421 1470
     /* update strut */
@@ -1436,6 +1485,7 @@ client_update_properties(lua_State *L, int cidx, client_t *c)
1436 1485
     property_update_net_wm_icon_name(c, net_wm_icon_name);
1437 1486
     property_update_wm_class(c, wm_class);
1438 1487
     property_update_wm_protocols(c, wm_protocols);
1488
+    property_update_motif_wm_hints(c, motif_wm_hints);
1439 1489
     window_set_opacity(L, cidx, xwindow_get_opacity_from_cookie(opacity));
1440 1490
 }
1441 1491
 
@@ -3156,6 +3206,78 @@ LUA_OBJECT_EXPORT_PROPERTY(client, client_t, maximized_vertical, lua_pushboolean
3156 3206
 LUA_OBJECT_EXPORT_PROPERTY(client, client_t, maximized, lua_pushboolean)
3157 3207
 LUA_OBJECT_EXPORT_PROPERTY(client, client_t, startup_id, lua_pushstring)
3158 3208
 
3209
+static int
3210
+luaA_client_get_motif_wm_hints(lua_State *L, client_t *c)
3211
+{
3212
+    if (!(c->motif_wm_hints.hints & MWM_HINTS_AWESOME_SET))
3213
+        return 0;
3214
+
3215
+    lua_newtable(L);
3216
+
3217
+#define HANDLE_BIT(field, flag, name) do { \
3218
+        lua_pushboolean(L, c->motif_wm_hints.field & flag); \
3219
+        lua_setfield(L, -2, name); \
3220
+    } while (0)
3221
+
3222
+    if (c->motif_wm_hints.hints & MWM_HINTS_FUNCTIONS)
3223
+    {
3224
+        lua_newtable(L);
3225
+        HANDLE_BIT(functions, MWM_FUNC_ALL, "all");
3226
+        HANDLE_BIT(functions, MWM_FUNC_RESIZE, "resize");
3227
+        HANDLE_BIT(functions, MWM_FUNC_MOVE, "move");
3228
+        HANDLE_BIT(functions, MWM_FUNC_MINIMIZE, "minimize");
3229
+        HANDLE_BIT(functions, MWM_FUNC_MAXIMIZE, "maximize");
3230
+        HANDLE_BIT(functions, MWM_FUNC_CLOSE, "close");
3231
+        lua_setfield(L, -2, "functions");
3232
+    }
3233
+
3234
+    if (c->motif_wm_hints.hints & MWM_HINTS_DECORATIONS)
3235
+    {
3236
+        lua_newtable(L);
3237
+        HANDLE_BIT(decorations, MWM_DECOR_ALL, "all");
3238
+        HANDLE_BIT(decorations, MWM_DECOR_BORDER, "border");
3239
+        HANDLE_BIT(decorations, MWM_DECOR_RESIZEH, "resizeh");
3240
+        HANDLE_BIT(decorations, MWM_DECOR_TITLE, "title");
3241
+        HANDLE_BIT(decorations, MWM_DECOR_MENU, "menu");
3242
+        HANDLE_BIT(decorations, MWM_DECOR_MINIMIZE, "minimize");
3243
+        HANDLE_BIT(decorations, MWM_DECOR_MAXIMIZE, "maximize");
3244
+        lua_setfield(L, -2, "decorations");
3245
+    }
3246
+
3247
+    if (c->motif_wm_hints.hints & MWM_HINTS_INPUT_MODE)
3248
+    {
3249
+        switch (c->motif_wm_hints.input_mode) {
3250
+        case MWM_INPUT_MODELESS:
3251
+            lua_pushliteral(L, "modeless");
3252
+            break;
3253
+        case MWM_INPUT_PRIMARY_APPLICATION_MODAL:
3254
+            lua_pushliteral(L, "primary_application_modal");
3255
+            break;
3256
+        case MWM_INPUT_SYSTEM_MODAL:
3257
+            lua_pushliteral(L, "system_modal");
3258
+            break;
3259
+        case MWM_INPUT_FULL_APPLICATION_MODAL:
3260
+            lua_pushliteral(L, "full_application_modal");
3261
+            break;
3262
+        default:
3263
+            lua_pushfstring(L, "unknown (%d)", (int) c->motif_wm_hints.input_mode);
3264
+            break;
3265
+        }
3266
+        lua_setfield(L, -2, "input_mode");
3267
+    }
3268
+
3269
+    if (c->motif_wm_hints.hints & MWM_HINTS_STATUS)
3270
+    {
3271
+        lua_newtable(L);
3272
+        HANDLE_BIT(status, MWM_TEAROFF_WINDOW, "tearoff_window");
3273
+        lua_setfield(L, -2, "status");
3274
+    }
3275
+
3276
+#undef HANDLE_BIT
3277
+
3278
+    return 1;
3279
+}
3280
+
3159 3281
 static int
3160 3282
 luaA_client_get_content(lua_State *L, client_t *c)
3161 3283
 {
@@ -3721,6 +3843,10 @@ client_class_setup(lua_State *L)
3721 3843
                             (lua_class_propfunc_t) luaA_client_set_modal,
3722 3844
                             (lua_class_propfunc_t) luaA_client_get_modal,
3723 3845
                             (lua_class_propfunc_t) luaA_client_set_modal);
3846
+    luaA_class_add_property(&client_class, "motif_wm_hints",
3847
+                            NULL,
3848
+                            (lua_class_propfunc_t) luaA_client_get_motif_wm_hints,
3849
+                            NULL);
3724 3850
     luaA_class_add_property(&client_class, "group_window",
3725 3851
                             NULL,
3726 3852
                             (lua_class_propfunc_t) luaA_client_get_group_window,

+ 45
- 0
objects/client.h View File

@@ -47,6 +47,48 @@ typedef enum {
47 47
     CLIENT_TITLEBAR_COUNT = 4
48 48
 } client_titlebar_t;
49 49
 
50
+/* Special bit we invented to "fake" unset hints */
51
+#define MWM_HINTS_AWESOME_SET   (1L << 15)
52
+
53
+/* The following is taken from MwmUtil.h and slightly adapted, which is
54
+ * copyright (c) 1987-2012, The Open Group.
55
+ * It is licensed under GPLv2 or later.
56
+ */
57
+#define MWM_HINTS_FUNCTIONS     (1L << 0)
58
+#define MWM_HINTS_DECORATIONS   (1L << 1)
59
+#define MWM_HINTS_INPUT_MODE    (1L << 2)
60
+#define MWM_HINTS_STATUS        (1L << 3)
61
+
62
+#define MWM_FUNC_ALL            (1L << 0)
63
+#define MWM_FUNC_RESIZE         (1L << 1)
64
+#define MWM_FUNC_MOVE           (1L << 2)
65
+#define MWM_FUNC_MINIMIZE       (1L << 3)
66
+#define MWM_FUNC_MAXIMIZE       (1L << 4)
67
+#define MWM_FUNC_CLOSE          (1L << 5)
68
+
69
+#define MWM_DECOR_ALL           (1L << 0)
70
+#define MWM_DECOR_BORDER        (1L << 1)
71
+#define MWM_DECOR_RESIZEH       (1L << 2)
72
+#define MWM_DECOR_TITLE         (1L << 3)
73
+#define MWM_DECOR_MENU          (1L << 4)
74
+#define MWM_DECOR_MINIMIZE      (1L << 5)
75
+#define MWM_DECOR_MAXIMIZE      (1L << 6)
76
+
77
+#define MWM_INPUT_MODELESS 0
78
+#define MWM_INPUT_PRIMARY_APPLICATION_MODAL 1
79
+#define MWM_INPUT_SYSTEM_MODAL 2
80
+#define MWM_INPUT_FULL_APPLICATION_MODAL 3
81
+
82
+#define MWM_TEAROFF_WINDOW    (1L<<0)
83
+
84
+typedef struct {
85
+    uint32_t hints;
86
+    uint32_t functions;
87
+    uint32_t decorations;
88
+    int32_t input_mode;
89
+    uint32_t status;
90
+} motif_wm_hints_t;
91
+
50 92
 /** client_t type */
51 93
 struct client_t
52 94
 {
@@ -143,6 +185,8 @@ struct client_t
143 185
         /** The drawable for this bar. */
144 186
         drawable_t *drawable;
145 187
     } titlebar[CLIENT_TITLEBAR_COUNT];
188
+    /** Motif WM hints, with an additional MWM_HINTS_AWESOME_SET bit */
189
+    motif_wm_hints_t motif_wm_hints;
146 190
 };
147 191
 
148 192
 ARRAY_FUNCS(client_t *, client, DO_NOTHING)
@@ -190,6 +234,7 @@ void client_set_group_window(lua_State *, int, xcb_window_t);
190 234
 void client_set_icons(client_t *, cairo_surface_array_t);
191 235
 void client_set_icon_from_pixmaps(client_t *, xcb_pixmap_t, xcb_pixmap_t);
192 236
 void client_set_skip_taskbar(lua_State *, int, bool);
237
+void client_set_motif_wm_hints(lua_State *, int, motif_wm_hints_t);
193 238
 void client_focus(client_t *);
194 239
 bool client_focus_update(client_t *);
195 240
 bool client_hasproto(client_t *, xcb_atom_t);

+ 39
- 0
property.c View File

@@ -91,6 +91,7 @@ HANDLE_PROPERTY(wm_hints)
91 91
 HANDLE_PROPERTY(wm_class)
92 92
 HANDLE_PROPERTY(net_wm_icon)
93 93
 HANDLE_PROPERTY(net_wm_pid)
94
+HANDLE_PROPERTY(motif_wm_hints)
94 95
 
95 96
 #undef HANDLE_PROPERTY
96 97
 
@@ -304,6 +305,41 @@ property_update_net_wm_pid(client_t *c, xcb_get_property_cookie_t cookie)
304 305
     p_delete(&reply);
305 306
 }
306 307
 
308
+xcb_get_property_cookie_t
309
+property_get_motif_wm_hints(client_t *c)
310
+{
311
+    return xcb_get_property_unchecked(globalconf.connection, false, c->window, _MOTIF_WM_HINTS, _MOTIF_WM_HINTS, 0L, 5L);
312
+}
313
+
314
+void
315
+property_update_motif_wm_hints(client_t *c, xcb_get_property_cookie_t cookie)
316
+{
317
+    motif_wm_hints_t hints;
318
+    xcb_get_property_reply_t *reply;
319
+    lua_State *L = globalconf_get_lua_State();
320
+
321
+    /* Clear the hints */
322
+    p_clear(&hints, 1);
323
+
324
+    reply = xcb_get_property_reply(globalconf.connection, cookie, NULL);
325
+
326
+    if(reply && reply->value_len == 5)
327
+    {
328
+        uint32_t *rdata = xcb_get_property_value(reply);
329
+        if(rdata)
330
+        {
331
+            memcpy(&hints, rdata, sizeof(hints));
332
+            hints.hints |= MWM_HINTS_AWESOME_SET;
333
+        }
334
+    }
335
+
336
+    p_delete(&reply);
337
+
338
+    luaA_object_push(L, c);
339
+    client_set_motif_wm_hints(L, -1, hints);
340
+    lua_pop(L, 1);
341
+}
342
+
307 343
 xcb_get_property_cookie_t
308 344
 property_get_wm_protocols(client_t *c)
309 345
 {
@@ -478,6 +514,9 @@ property_handle_propertynotify(xcb_property_notify_event_t *ev)
478 514
     HANDLE(_NET_WM_PID, property_handle_net_wm_pid)
479 515
     HANDLE(_NET_WM_WINDOW_OPACITY, property_handle_net_wm_opacity)
480 516
 
517
+    /* MOTIF hints */
518
+    HANDLE(_MOTIF_WM_HINTS, property_handle_motif_wm_hints)
519
+
481 520
     /* background change */
482 521
     HANDLE(_XROOTPMAP_ID, property_handle_xrootpmap_id)
483 522
 

+ 1
- 0
property.h View File

@@ -42,6 +42,7 @@ PROPERTY(wm_class);
42 42
 PROPERTY(wm_protocols);
43 43
 PROPERTY(net_wm_pid);
44 44
 PROPERTY(net_wm_icon);
45
+PROPERTY(motif_wm_hints);
45 46
 
46 47
 #undef PROPERTY
47 48
 

Loading…
Cancel
Save