aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authordec05eba <dec05eba@protonmail.com>2023-12-08 18:04:07 +0100
committerdec05eba <dec05eba@protonmail.com>2023-12-08 18:04:07 +0100
commitb3c534bdeb82f31d1a30d609b2fe42c128d9b560 (patch)
tree5fd2b200b377ac9497caa3aff0d86552a0c0515d
parentb756fb4fa5ed540ea37139d45def2f3f1151b19e (diff)
Add class hint, wm name, window type
-rw-r--r--include/mgl/window/window.h7
-rw-r--r--src/window/window.c48
2 files changed, 50 insertions, 5 deletions
diff --git a/include/mgl/window/window.h b/include/mgl/window/window.h
index cbcdb1a..12a7aef 100644
--- a/include/mgl/window/window.h
+++ b/include/mgl/window/window.h
@@ -60,6 +60,11 @@ struct mgl_window {
int num_monitors;
};
+typedef enum {
+ MGL_WINDOW_TYPE_NORMAL,
+ MGL_WINDOW_TYPE_DIALOG
+} mgl_window_type;
+
/* TODO: Some of these parameters only apply to new window */
typedef struct {
mgl_vec2i position;
@@ -71,6 +76,8 @@ typedef struct {
bool override_redirect; /* false by default */
bool support_alpha; /* support alpha for the window, false by default */
mgl_color background_color; /* default: black */
+ const char *class_name;
+ mgl_window_type window_type; /* default: normal */
} mgl_window_create_params;
typedef enum {
diff --git a/src/window/window.c b/src/window/window.c
index 72f8598..ba4e8d5 100644
--- a/src/window/window.c
+++ b/src/window/window.c
@@ -69,7 +69,12 @@ typedef struct {
Atom image_gif_atom;
Atom incr_atom;
Atom net_wm_state_atom;
- Atom wm_state_fullscreen_atom;
+ Atom net_wm_state_fullscreen_atom;
+ Atom net_wm_state_above_atom;
+ Atom net_wm_name_atom;
+ Atom net_wm_window_type_atom;
+ Atom net_wm_window_type_normal_atom;
+ Atom net_wm_window_type_dialog_atom;
Cursor default_cursor;
Cursor invisible_cursor;
unsigned int prev_keycode_pressed;
@@ -160,7 +165,12 @@ static int x11_context_init(x11_context *self, bool alpha) {
self->image_gif_atom = XInternAtom(context->connection, "image/gif", False);
self->incr_atom = XInternAtom(context->connection, "INCR", False);
self->net_wm_state_atom = XInternAtom(context->connection, "_NET_WM_STATE", False);
- self->wm_state_fullscreen_atom = XInternAtom(context->connection, "_NET_WM_STATE_FULLSCREEN", False);
+ self->net_wm_state_fullscreen_atom = XInternAtom(context->connection, "_NET_WM_STATE_FULLSCREEN", False);
+ self->net_wm_state_above_atom = XInternAtom(context->connection, "_NET_WM_STATE_ABOVE", False);
+ self->net_wm_name_atom = XInternAtom(context->connection, "_NET_WM_NAME", False);
+ self->net_wm_window_type_atom = XInternAtom(context->connection, "_NET_WM_WINDOW_TYPE", False);
+ self->net_wm_window_type_normal_atom = XInternAtom(context->connection, "_NET_WM_WINDOW_TYPE_NORMAL", False);
+ self->net_wm_window_type_dialog_atom = XInternAtom(context->connection, "_NET_WM_WINDOW_TYPE_DIALOG", False);
self->default_cursor = None;
self->invisible_cursor = None;
@@ -473,6 +483,22 @@ static unsigned long mgl_color_to_x11_pixel(mgl_color color) {
return ((uint32_t)color.a << 24) | ((uint32_t)color.r << 16) | ((uint32_t)color.g << 8) | (uint32_t)color.b;
}
+static void mgl_set_window_type(mgl_window *self, mgl_window_type window_type) {
+ mgl_context *context = mgl_get_context();
+ x11_context *x11_context = self->context;
+ switch(window_type) {
+ case MGL_WINDOW_TYPE_NORMAL: {
+ XChangeProperty(context->connection, self->window, x11_context->net_wm_window_type_atom, XA_ATOM, 32, PropModeReplace, (unsigned char*)&x11_context->net_wm_window_type_normal_atom, 1L);
+ break;
+ }
+ case MGL_WINDOW_TYPE_DIALOG: {
+ XChangeProperty(context->connection, self->window, x11_context->net_wm_window_type_atom, XA_ATOM, 32, PropModeReplace, (unsigned char*)&x11_context->net_wm_window_type_dialog_atom, 1L);
+ XChangeProperty(context->connection, self->window, x11_context->net_wm_state_atom, XA_ATOM, 32, PropModeReplace, (unsigned char*)&x11_context->net_wm_state_above_atom, 1L);
+ break;
+ }
+ }
+}
+
static int mgl_window_init(mgl_window *self, const char *title, const mgl_window_create_params *params, Window existing_window) {
self->window = 0;
self->context = NULL;
@@ -573,7 +599,7 @@ static int mgl_window_init(mgl_window *self, const char *title, const mgl_window
return -1;
}
- XStoreName(context->connection, self->window, title);
+ mgl_window_set_title(self, title);
if(!hide_window)
XMapWindow(context->connection, self->window);
}
@@ -594,6 +620,14 @@ static int mgl_window_init(mgl_window *self, const char *title, const mgl_window
32, PropModeReplace, (const unsigned char*)&pid, 1);
}
+ if(params && params->class_name) {
+ XClassHint class_hint = { params->class_name, params->class_name };
+ XSetClassHint(context->connection, self->window, &class_hint);
+ }
+
+ mgl_window_type window_type = params ? params->window_type : MGL_WINDOW_TYPE_NORMAL;
+ mgl_set_window_type(self, window_type);
+
XFlush(context->connection);
/* TODO: Check for failure? */
@@ -1306,7 +1340,11 @@ void mgl_window_close(mgl_window *self) {
void mgl_window_set_title(mgl_window *self, const char *title) {
mgl_context *context = mgl_get_context();
+ x11_context *x11_context = self->context;
+
XStoreName(context->connection, self->window, title);
+ XChangeProperty(context->connection, self->window, x11_context->net_wm_name_atom, x11_context->utf8_string_atom, 8, PropModeReplace, (unsigned char*)title, strlen(title));
+ XFlush(context->connection);
}
void mgl_window_set_cursor_visible(mgl_window *self, bool visible) {
@@ -1341,7 +1379,7 @@ void mgl_window_set_fullscreen(mgl_window *self, bool fullscreen) {
xev.xclient.message_type = x11_context->net_wm_state_atom;
xev.xclient.format = 32;
xev.xclient.data.l[0] = fullscreen ? 1 : 0;
- xev.xclient.data.l[1] = x11_context->wm_state_fullscreen_atom;
+ xev.xclient.data.l[1] = x11_context->net_wm_state_fullscreen_atom;
xev.xclient.data.l[2] = 0;
xev.xclient.data.l[3] = 1;
xev.xclient.data.l[4] = 0;
@@ -1365,7 +1403,7 @@ bool mgl_window_is_fullscreen(const mgl_window *self) {
unsigned long remaining_bytes = 0;
unsigned char *data = NULL;
if(XGetWindowProperty(context->connection, self->window, x11_context->net_wm_state_atom, 0, 1024, False, PropertyNewValue, &type, &format, &items, &remaining_bytes, &data) == Success && data) {
- is_fullscreen = format == 32 && *(unsigned long*)data == x11_context->wm_state_fullscreen_atom;
+ is_fullscreen = format == 32 && *(unsigned long*)data == x11_context->net_wm_state_fullscreen_atom;
XFree(data);
}
return is_fullscreen;