Skip to content
Snippets Groups Projects
Commit f2918676 authored by Deucе's avatar Deucе :ok_hand_tone4:
Browse files

More rabidly comply with ICCM and EWMH

While we're hacking on that, make a first attempt at a generic
Atom access framework.

The only actual visible change that should occur here is that the
window will not resize larger than will fit on the current desktop
between various WM widgets (panels and menus).  I've been considering
this change for a while, but now that fullscreen support is present,
it doesn't really take anything away.
parent 90c92455
No related branches found
No related tags found
1 merge request!463MRC mods by Codefenix (2024-10-20)
Pipeline #4424 passed
...@@ -52,10 +52,10 @@ sem_t mode_set; ...@@ -52,10 +52,10 @@ sem_t mode_set;
int x11_window_xpos; int x11_window_xpos;
int x11_window_ypos; int x11_window_ypos;
int x11_initialized=0; int x11_initialized=0;
sem_t event_thread_complete; static sem_t event_thread_complete;
int terminate = 0; static int terminate = 0;
Atom copybuf_format; Atom copybuf_format;
Atom pastebuf_format; static Atom pastebuf_format;
bool xrender_found; bool xrender_found;
bool xinerama_found; bool xinerama_found;
bool xrandr_found; bool xrandr_found;
...@@ -65,16 +65,82 @@ bool x_internal_scaling = true; ...@@ -65,16 +65,82 @@ bool x_internal_scaling = true;
* Local variables * Local variables
*/ */
enum UsedAtom {
// UTF8_STRING: https://www.pps.jussieu.fr/~jch/software/UTF8_STRING/UTF8_STRING.text
ATOM_UTF8_STRING,
// ICCM: https://x.org/releases/X11R7.6/doc/xorg-docs/specs/ICCCM/icccm.html
ATOM_TARGETS,
ATOM_WM_CLASS,
ATOM_WM_DELETE_WINDOW,
// EWMH: https://specifications.freedesktop.org/wm-spec/wm-spec-1.3.html
ATOM__NET_FRAME_EXTENTS,
ATOM__NET_SUPPORTED,
ATOM__NET_SUPPORTING_WM_CHECK,
ATOM__NET_WM_DESKTOP,
ATOM__NET_WM_ICON,
ATOM__NET_WM_ICON_NAME,
ATOM__NET_WM_NAME,
ATOM__NET_WM_PID,
ATOM__NET_WM_PING,
ATOM__NET_WM_STATE,
ATOM__NET_WM_STATE_FULLSCREEN,
ATOM__NET_WM_STATE_MAXIMIZED_VERT,
ATOM__NET_WM_STATE_MAXIMIZED_HORZ,
ATOM__NET_WM_WINDOW_TYPE,
ATOM__NET_WM_WINDOW_TYPE_NORMAL,
ATOM__NET_WORKAREA,
ATOMCOUNT
};
enum AtomStandard {
UTF8_ATOM,
ICCM_ATOM,
EWMH_ATOM
};
static uint32_t supported_standards;
#define XA_UTF8_STRING (0x10000000UL)
static struct AtomDef {
const char * const name;
const enum AtomStandard standard;
Atom req_type;
const int format;
Atom atom;
bool supported;
} SupportedAtoms[ATOMCOUNT] = {
// UTF8_STRING: https://www.pps.jussieu.fr/~jch/software/UTF8_STRING/UTF8_STRING.text
{"UTF8_STRING", UTF8_ATOM, None, 0, None, false},
// ICCM: https://x.org/releases/X11R7.6/doc/xorg-docs/specs/ICCCM/icccm.html
{"TARGETS", ICCM_ATOM, XA_ATOM, 32, None, false},
{"WM_CLASS", ICCM_ATOM, XA_STRING, 8, None, false},
{"WM_DELETE_WINDOW", ICCM_ATOM, None, 0, None, false},
// EWMH: https://specifications.freedesktop.org/wm-spec/wm-spec-1.3.html
{"_NET_FRAME_EXTENTS", EWMH_ATOM, XA_CARDINAL, 32, None, false},
{"_NET_SUPPORTED", EWMH_ATOM, XA_ATOM, 32, None, false},
{"_NET_SUPPORTING_WM_CHECK", EWMH_ATOM, XA_WINDOW, 32, None, false},
{"_NET_WM_DESKTOP", EWMH_ATOM, XA_CARDINAL, 32, None, false},
{"_NET_WM_ICON", EWMH_ATOM, XA_CARDINAL, 32, None, false},
{"_NET_WM_ICON_NAME", EWMH_ATOM, XA_UTF8_STRING, 8, None, false},
{"_NET_WM_NAME", EWMH_ATOM, XA_UTF8_STRING, 8, None, false},
{"_NET_WM_PID", EWMH_ATOM, XA_CARDINAL, 32, None, false},
{"_NET_WM_PING", EWMH_ATOM, None, 0, None, false},
{"_NET_WM_STATE", EWMH_ATOM, XA_ATOM, 32, None, false},
{"_NET_WM_STATE_FULLSCREEN", EWMH_ATOM, None, 0, None, false},
{"_NET_WM_STATE_MAXIMIZED_VERT", EWMH_ATOM, None, 0, None, false},
{"_NET_WM_STATE_MAXIMIZED_HORZ", EWMH_ATOM, None, 0, None, false},
{"_NET_WM_WINDOW_TYPE", EWMH_ATOM, XA_ATOM, 32, None, false},
{"_NET_WM_WINDOW_TYPE_NORMAL", EWMH_ATOM, None, 0, None, false},
{"_NET_WORKAREA", EWMH_ATOM, XA_CARDINAL, 4, None, false},
};
#define A(name) SupportedAtoms[ATOM_ ## name].atom
/* Sets the atom to be used for copy/paste operations */ /* Sets the atom to be used for copy/paste operations */
#define CONSOLE_CLIPBOARD XA_PRIMARY #define CONSOLE_CLIPBOARD XA_PRIMARY
static Atom WM_DELETE_WINDOW = None;
static Atom _NET_WM_PING = None;
static Atom _NET_WM_STATE = None;
static const long _NET_WM_STATE_REMOVE = 0; static const long _NET_WM_STATE_REMOVE = 0;
static const long _NET_WM_STATE_ADD = 1; static const long _NET_WM_STATE_ADD = 1;
static Atom _NET_WM_STATE_FULLSCREEN = None;
static Atom _NET_WM_STATE_MAXIMIZED_VERT = None;
static Atom _NET_WM_STATE_MAXIMIZED_HORZ = None;
static Display *dpy=NULL; static Display *dpy=NULL;
static Window win; static Window win;
...@@ -226,6 +292,124 @@ static struct { ...@@ -226,6 +292,124 @@ static struct {
{ 0x8600, 0x5888, 0x8a00, 0x8c00 }, /* key 88 - F12 */ { 0x8600, 0x5888, 0x8a00, 0x8c00 }, /* key 88 - F12 */
}; };
static struct AtomDef *
get_atom_def(Atom atom)
{
enum UsedAtom a;
for (a = 0; a < ATOMCOUNT; a++) {
if (SupportedAtoms[a].atom == atom)
return &SupportedAtoms[a];
}
return NULL;
}
static void
initialize_atoms(void)
{
enum UsedAtom a;
Atom atr;
int afr;
unsigned long nir;
unsigned long bytes_left = 4;
unsigned char *prop = NULL;
Window w;
Atom atom;
struct AtomDef *ad;
long offset;
supported_standards |= (1 << UTF8_ATOM);
supported_standards |= (1 << ICCM_ATOM);
for (a = 0; a < ATOMCOUNT; a++) {
SupportedAtoms[a].atom = x11.XInternAtom(dpy, (char *)SupportedAtoms[a].name, False);
}
if (A(UTF8_STRING) == None)
supported_standards &= ~(1 << UTF8_ATOM);
if (supported_standards & (1 << UTF8_ATOM)) {
if (x11.XGetWindowProperty(dpy, root, A(_NET_SUPPORTING_WM_CHECK), 0, 1, False, XA_WINDOW, &atr, &afr, &nir, &bytes_left, &prop) == Success) {
if (atr == XA_WINDOW) {
if (nir == 1) {
w = *(Window *)prop;
x11.XFree(prop);
prop = NULL;
if (x11.XGetWindowProperty(dpy, w, A(_NET_SUPPORTING_WM_CHECK), 0, 1, False, XA_WINDOW, &atr, &afr, &nir, &bytes_left, &prop) == Success) {
if (atr == XA_WINDOW) {
if (nir == 1) {
if (w == *(Window *)prop) {
supported_standards |= (1 << EWMH_ATOM);
}
}
}
}
}
}
if (prop != NULL)
x11.XFree(prop);
}
}
if (!(supported_standards & (1 << EWMH_ATOM))) {
for (a = 0; a < ATOMCOUNT; a++) {
if (SupportedAtoms[a].standard == EWMH_ATOM)
SupportedAtoms[a].atom = None;
}
}
else {
for (offset = 0, bytes_left = 1; bytes_left; offset += nir) {
if (x11.XGetWindowProperty(dpy, root, A(_NET_SUPPORTED), offset, 1, False, XA_ATOM, &atr, &afr, &nir, &bytes_left, &prop) != Success)
break;
if (atr != XA_ATOM) {
x11.XFree(prop);
break;
}
atom = *(Atom *)prop;
x11.XFree(prop);
if (atom != None) {
ad = get_atom_def(atom);
if (ad != NULL)
ad->supported = true;
}
}
for (a = 0; a < ATOMCOUNT; a++) {
if (SupportedAtoms[a].atom != None) {
if (SupportedAtoms[a].standard != EWMH_ATOM)
SupportedAtoms[a].supported = true;
if (!SupportedAtoms[a].supported) {
SupportedAtoms[a].atom = None;
}
}
}
}
for (a = 0; a < ATOMCOUNT; a++) {
if (SupportedAtoms[a].req_type == XA_UTF8_STRING) {
if (A(UTF8_STRING) == None) {
SupportedAtoms[a].supported = false;
SupportedAtoms[a].atom = None;
}
else {
SupportedAtoms[a].req_type = A(UTF8_STRING);
}
}
}
}
static bool
set_win_property(enum UsedAtom atom, Atom type, int format, int action, const void *value, int count)
{
struct AtomDef *ad = &SupportedAtoms[atom];
if (ad->atom == None)
return false;
if (!(supported_standards & (1 << ad->standard)))
return false;
return (x11.XChangeProperty(dpy, win, ad->atom, type, format, action, (unsigned char *)value, count) != 0);
}
static bool static bool
fullscreen_geometry(int *x_org, int *y_org, int *width, int *height) fullscreen_geometry(int *x_org, int *y_org, int *width, int *height)
{ {
...@@ -358,8 +542,9 @@ x11_get_maxsize(int *w, int *h) ...@@ -358,8 +542,9 @@ x11_get_maxsize(int *w, int *h)
int afr; int afr;
long *ret; long *ret;
unsigned long nir; unsigned long nir;
unsigned long bytes_left = 4; unsigned long bytes_left;
unsigned char *prop; unsigned char *prop;
long desktop = -1;
if (dpy == NULL) if (dpy == NULL)
return false; return false;
...@@ -369,20 +554,24 @@ x11_get_maxsize(int *w, int *h) ...@@ -369,20 +554,24 @@ x11_get_maxsize(int *w, int *h)
} }
else { else {
// First, try to get _NET_WORKAREA... // First, try to get _NET_WORKAREA...
if (x11.workarea == None) { if (A(_NET_WM_DESKTOP) != None && win != 0) {
x11.workarea = x11.XInternAtom(dpy, "_NET_WORKAREA", True); if (x11.XGetWindowProperty(dpy, win, A(_NET_WM_DESKTOP), 0, 1, False, XA_CARDINAL, &atr, &afr, &nir, &bytes_left, &prop) == Success) {
if (atr == XA_CARDINAL && afr == 32 && nir > 0) {
desktop = *(long *)prop;
}
x11.XFree(prop);
}
} }
if (x11.workarea != None) { if (A(_NET_WORKAREA) != None) {
for (i = 0, offset = 0; bytes_left; i++) { for (i = 0, offset = 0, bytes_left = 1; bytes_left; i++, offset += nir) {
if (x11.XGetWindowProperty(dpy, root, x11.workarea, offset, 4, False, XA_CARDINAL, &atr, &afr, &nir, &bytes_left, &prop) != Success) if (x11.XGetWindowProperty(dpy, root, A(_NET_WORKAREA), offset, 4, False, XA_CARDINAL, &atr, &afr, &nir, &bytes_left, &prop) != Success)
break; break;
if (atr != XA_CARDINAL) { if (atr != XA_CARDINAL) {
x11.XFree(prop); x11.XFree(prop);
break; break;
} }
if (nir > 0)
offset += nir;
ret = (long *)prop; ret = (long *)prop;
if (desktop == -1) {
if (nir >= 3) { if (nir >= 3) {
if (ret[2] > maxw) if (ret[2] > maxw)
maxw = ret[2]; maxw = ret[2];
...@@ -391,10 +580,31 @@ x11_get_maxsize(int *w, int *h) ...@@ -391,10 +580,31 @@ x11_get_maxsize(int *w, int *h)
if (ret[3] > maxh) if (ret[3] > maxh)
maxh = ret[3]; maxh = ret[3];
} }
}
else if (desktop == i) {
if (nir >= 3)
maxw = ret[2];
if (nir >= 4)
maxh = ret[3];
x11.XFree(prop);
break;
}
x11.XFree(prop);
}
}
if (maxw > 0 && maxh > 0) {
if (A(_NET_FRAME_EXTENTS) != None && win != 0) {
if (x11.XGetWindowProperty(dpy, win, A(_NET_FRAME_EXTENTS), 0, 4, False, XA_CARDINAL, &atr, &afr, &nir, &bytes_left, &prop) == Success) {
if (atr == XA_CARDINAL && afr == 32 && nir == 4) {
ret = (long *)prop;
maxw -= ret[0] + ret[1];
maxh -= ret[2] + ret[3];
}
x11.XFree(prop); x11.XFree(prop);
} }
} }
} }
}
// Couldn't get work area, get size of screen instead. :( // Couldn't get work area, get size of screen instead. :(
if (maxw == 0 || maxh == 0) { if (maxw == 0 || maxh == 0) {
...@@ -659,11 +869,14 @@ static int init_window() ...@@ -659,11 +869,14 @@ static int init_window()
int mw, mh; int mw, mh;
int screen; int screen;
int major, minor; int major, minor;
unsigned long pid_l;
Atom a;
dpy = x11.XOpenDisplay(NULL); dpy = x11.XOpenDisplay(NULL);
if (dpy == NULL) { if (dpy == NULL) {
return(-1); return(-1);
} }
root = DefaultRootWindow(dpy);
x11.XSynchronize(dpy, False); x11.XSynchronize(dpy, False);
#ifdef WITH_XRENDER #ifdef WITH_XRENDER
...@@ -680,9 +893,7 @@ static int init_window() ...@@ -680,9 +893,7 @@ static int init_window()
#endif #endif
xfd = ConnectionNumber(dpy); xfd = ConnectionNumber(dpy);
x11.utf8 = x11.XInternAtom(dpy, "UTF8_STRING", False); initialize_atoms();
x11.targets = x11.XInternAtom(dpy, "TARGETS", False);
x11.workarea = x11.XInternAtom(dpy, "_NET_WORKAREA", True);
screen = DefaultScreen(dpy); screen = DefaultScreen(dpy);
#ifdef DefaultVisual #ifdef DefaultVisual
...@@ -711,7 +922,6 @@ static int init_window() ...@@ -711,7 +922,6 @@ static int init_window()
/* Create window, but defer setting a size and GC. */ /* Create window, but defer setting a size and GC. */
XSetWindowAttributes wa = {0}; XSetWindowAttributes wa = {0};
root = DefaultRootWindow(dpy);
parent = root; parent = root;
wincmap = x11.XCreateColormap(dpy, root, visual, AllocNone); wincmap = x11.XCreateColormap(dpy, root, visual, AllocNone);
x11.XInstallColormap(dpy, wincmap); x11.XInstallColormap(dpy, wincmap);
...@@ -743,12 +953,13 @@ static int init_window() ...@@ -743,12 +953,13 @@ static int init_window()
x11.XSetWMProperties(dpy, win, NULL, NULL, 0, 0, NULL, wmhints, classhints); x11.XSetWMProperties(dpy, win, NULL, NULL, 0, 0, NULL, wmhints, classhints);
x11.XFree(wmhints); x11.XFree(wmhints);
} }
set_win_property(A(_NET_WM_ICON), XA_CARDINAL, 32, PropModeReplace, ciolib_initial_icon, ciolib_initial_icon_width * ciolib_initial_icon_width);
Atom pid_atom = x11.XInternAtom(dpy, "_NET_WM_PID", False); pid_l = getpid();
if (pid_atom != None) { set_win_property(ATOM__NET_WM_PID, XA_CARDINAL, 32, PropModeReplace, &pid_l, 1);
unsigned long pid_l = getpid(); a = A(_NET_WM_WINDOW_TYPE_NORMAL);
x11.XChangeProperty(dpy, win, pid_atom, XA_CARDINAL, 32, PropModeReplace, (unsigned char *)&pid_l, 1); if (a != None)
} set_win_property(ATOM__NET_WM_WINDOW_TYPE, XA_ATOM, 32, PropModeReplace, &a, 1);
im = x11.XOpenIM(dpy, NULL, "CIOLIB", "CIOLIB"); im = x11.XOpenIM(dpy, NULL, "CIOLIB", "CIOLIB");
if (im != NULL) { if (im != NULL) {
...@@ -760,13 +971,6 @@ static int init_window() ...@@ -760,13 +971,6 @@ static int init_window()
if (classhints) if (classhints)
x11.XFree(classhints); x11.XFree(classhints);
WM_DELETE_WINDOW = x11.XInternAtom(dpy, "WM_DELETE_WINDOW", False);
_NET_WM_PING = x11.XInternAtom(dpy, "_NET_WM_PING", False);
_NET_WM_STATE = x11.XInternAtom(dpy, "_NET_WM_STATE", False);
_NET_WM_STATE_FULLSCREEN = x11.XInternAtom(dpy, "_NET_WM_STATE_FULLSCREEN", False);
_NET_WM_STATE_MAXIMIZED_VERT = x11.XInternAtom(dpy, "_NET_WM_STATE_MAXIMIZED_VERT", False);
_NET_WM_STATE_MAXIMIZED_HORZ = x11.XInternAtom(dpy, "_NET_WM_STATE_MAXIMIZED_HORZ", False);
gcv.function = GXcopy; gcv.function = GXcopy;
gcv.foreground = black | 0xff000000; gcv.foreground = black | 0xff000000;
gcv.background = white; gcv.background = white;
...@@ -780,10 +984,10 @@ static int init_window() ...@@ -780,10 +984,10 @@ static int init_window()
x11.XStoreName(dpy, win, "SyncConsole"); x11.XStoreName(dpy, win, "SyncConsole");
Atom protos[2]; Atom protos[2];
int i = 0; int i = 0;
if (WM_DELETE_WINDOW != None) if (A(WM_DELETE_WINDOW) != None)
protos[i++] = WM_DELETE_WINDOW; protos[i++] = A(WM_DELETE_WINDOW);
if (_NET_WM_PING != None) if (A(_NET_WM_PING) != None)
protos[i++] = _NET_WM_PING; protos[i++] = A(_NET_WM_PING);
if (i) if (i)
x11.XSetWMProtocols(dpy, win, protos, i); x11.XSetWMProtocols(dpy, win, protos, i);
...@@ -797,18 +1001,18 @@ send_fullscreen(bool set) ...@@ -797,18 +1001,18 @@ send_fullscreen(bool set)
XEvent ev = {0}; XEvent ev = {0};
bool ret = false; bool ret = false;
if (_NET_WM_STATE != None && _NET_WM_STATE_FULLSCREEN != None) { if (A(_NET_WM_STATE) != None && A(_NET_WM_STATE_FULLSCREEN) != None) {
if (last != set) { if (last != set) {
ev.xclient.type = ClientMessage; ev.xclient.type = ClientMessage;
ev.xclient.serial = 0; // Populated by XSendEvent ev.xclient.serial = 0; // Populated by XSendEvent
ev.xclient.send_event = True; // Populated by XSendEvent ev.xclient.send_event = True; // Populated by XSendEvent
ev.xclient.display = dpy; ev.xclient.display = dpy;
ev.xclient.window = win; ev.xclient.window = win;
ev.xclient.message_type = _NET_WM_STATE; ev.xclient.message_type = A(_NET_WM_STATE);
ev.xclient.format = 32; ev.xclient.format = 32;
memset(&ev.xclient.data.l, 0, sizeof(ev.xclient.data.l)); memset(&ev.xclient.data.l, 0, sizeof(ev.xclient.data.l));
ev.xclient.data.l[0] = set ? _NET_WM_STATE_ADD : _NET_WM_STATE_REMOVE; ev.xclient.data.l[0] = set ? _NET_WM_STATE_ADD : _NET_WM_STATE_REMOVE;
ev.xclient.data.l[1] = _NET_WM_STATE_FULLSCREEN; ev.xclient.data.l[1] = A(_NET_WM_STATE_FULLSCREEN);
ev.xclient.data.l[3] = 1; ev.xclient.data.l[3] = 1;
ret = x11.XSendEvent(dpy, root, False, SubstructureNotifyMask | SubstructureRedirectMask, &ev) != 0; ret = x11.XSendEvent(dpy, root, False, SubstructureNotifyMask | SubstructureRedirectMask, &ev) != 0;
if (ret) { if (ret) {
...@@ -1257,16 +1461,16 @@ is_maximized(void) ...@@ -1257,16 +1461,16 @@ is_maximized(void)
unsigned char *prop; unsigned char *prop;
size_t offset; size_t offset;
if (_NET_WM_STATE != None) { if (A(_NET_WM_STATE) != None) {
for (offset = 0; bytes_left; offset += nir) { for (offset = 0; bytes_left; offset += nir) {
if (x11.XGetWindowProperty(dpy, win, _NET_WM_STATE, offset, 1, False, XA_ATOM, &atr, &afr, &nir, &bytes_left, &prop) != Success) if (x11.XGetWindowProperty(dpy, win, A(_NET_WM_STATE), offset, 1, False, XA_ATOM, &atr, &afr, &nir, &bytes_left, &prop) != Success)
break; break;
if (atr != XA_ATOM) { if (atr != XA_ATOM) {
x11.XFree(prop); x11.XFree(prop);
break; break;
} }
ret = (Atom *)prop; ret = (Atom *)prop;
if (*ret == _NET_WM_STATE_MAXIMIZED_VERT || *ret == _NET_WM_STATE_MAXIMIZED_HORZ) if (*ret == A(_NET_WM_STATE_MAXIMIZED_VERT) || *ret == A(_NET_WM_STATE_MAXIMIZED_HORZ))
is = true; is = true;
x11.XFree(prop); x11.XFree(prop);
if (is) if (is)
...@@ -1285,15 +1489,22 @@ static int x11_event(XEvent *ev) ...@@ -1285,15 +1489,22 @@ static int x11_event(XEvent *ev)
parent = ev->xreparent.parent; parent = ev->xreparent.parent;
break; break;
case ClientMessage: case ClientMessage:
if (ev->xclient.format == 32 && ev->xclient.data.l[0] == WM_DELETE_WINDOW && WM_DELETE_WINDOW != None) { if (ev->xclient.format == 32 && ev->xclient.data.l[0] == A(WM_DELETE_WINDOW) && A(WM_DELETE_WINDOW) != None) {
uint16_t key=CIO_KEY_QUIT; uint16_t key=CIO_KEY_QUIT;
write(key_pipe[1], &key, 2); write(key_pipe[1], &key, 2);
} }
else if(ev->xclient.format == 32 && ev->xclient.data.l[0] == _NET_WM_PING && _NET_WM_PING != None) { else if(ev->xclient.format == 32 && ev->xclient.data.l[0] == A(_NET_WM_PING) && A(_NET_WM_PING) != None) {
ev->xclient.window = root; ev->xclient.window = root;
x11.XSendEvent(dpy, ev->xclient.window, False, SubstructureNotifyMask | SubstructureRedirectMask, ev); x11.XSendEvent(dpy, ev->xclient.window, False, SubstructureNotifyMask | SubstructureRedirectMask, ev);
} }
break; break;
case PropertyNotify:
if (A(_NET_FRAME_EXTENTS) != None) {
if (ev->xproperty.atom != A(_NET_FRAME_EXTENTS))
break;
map_window();
}
break;
/* Graphics related events */ /* Graphics related events */
case ConfigureNotify: { case ConfigureNotify: {
bool resize = false; bool resize = false;
...@@ -1360,7 +1571,7 @@ static int x11_event(XEvent *ev) ...@@ -1360,7 +1571,7 @@ static int x11_event(XEvent *ev)
x11.XGetWindowProperty(dpy, win, ev->xselection.property, 0, 0, True, AnyPropertyType, &pastebuf_format, &format, &len, &bytes_left, (unsigned char **)(&pastebuf)); x11.XGetWindowProperty(dpy, win, ev->xselection.property, 0, 0, True, AnyPropertyType, &pastebuf_format, &format, &len, &bytes_left, (unsigned char **)(&pastebuf));
if(bytes_left > 0 && format==8) { if(bytes_left > 0 && format==8) {
x11.XGetWindowProperty(dpy, win, ev->xselection.property, 0, bytes_left, True, AnyPropertyType, &pastebuf_format, &format, &len, &dummy, (unsigned char **)&pastebuf); x11.XGetWindowProperty(dpy, win, ev->xselection.property, 0, bytes_left, True, AnyPropertyType, &pastebuf_format, &format, &len, &dummy, (unsigned char **)&pastebuf);
if (x11.utf8 && pastebuf_format == x11.utf8) { if (A(UTF8_STRING) && pastebuf_format == A(UTF8_STRING)) {
char *opb = pastebuf; char *opb = pastebuf;
pastebuf = (char *)utf8_to_cp(CIOLIB_ISO_8859_1, (uint8_t *)pastebuf, '?', strlen(pastebuf), NULL); pastebuf = (char *)utf8_to_cp(CIOLIB_ISO_8859_1, (uint8_t *)pastebuf, '?', strlen(pastebuf), NULL);
if (pastebuf == NULL) if (pastebuf == NULL)
...@@ -1378,7 +1589,7 @@ static int x11_event(XEvent *ev) ...@@ -1378,7 +1589,7 @@ static int x11_event(XEvent *ev)
/* Set paste buffer */ /* Set paste buffer */
sem_post(&pastebuf_set); sem_post(&pastebuf_set);
sem_wait(&pastebuf_used); sem_wait(&pastebuf_used);
if (x11.utf8 && pastebuf_format == x11.utf8) if (A(UTF8_STRING) && pastebuf_format == A(UTF8_STRING))
free(pastebuf); free(pastebuf);
else else
x11.XFree(pastebuf); x11.XFree(pastebuf);
...@@ -1394,8 +1605,6 @@ static int x11_event(XEvent *ev) ...@@ -1394,8 +1605,6 @@ static int x11_event(XEvent *ev)
req=&(ev->xselectionrequest); req=&(ev->xselectionrequest);
pthread_mutex_lock(&copybuf_mutex); pthread_mutex_lock(&copybuf_mutex);
if (x11.targets == 0)
x11.targets = x11.XInternAtom(dpy, "TARGETS", False);
respond.xselection.property=None; respond.xselection.property=None;
if(copybuf!=NULL) { if(copybuf!=NULL) {
if(req->target==XA_STRING) { if(req->target==XA_STRING) {
...@@ -1406,18 +1615,15 @@ static int x11_event(XEvent *ev) ...@@ -1406,18 +1615,15 @@ static int x11_event(XEvent *ev)
free(cpstr); free(cpstr);
} }
} }
else if(req->target == x11.utf8) { else if(req->target == A(UTF8_STRING)) {
x11.XChangeProperty(dpy, req->requestor, req->property, x11.utf8, 8, PropModeReplace, (uint8_t *)copybuf, strlen((char *)copybuf)); x11.XChangeProperty(dpy, req->requestor, req->property, A(UTF8_STRING), 8, PropModeReplace, (uint8_t *)copybuf, strlen((char *)copybuf));
respond.xselection.property=req->property; respond.xselection.property=req->property;
} }
else if(req->target == x11.targets) { else if(req->target == A(TARGETS)) {
if (x11.utf8 == 0) supported[count++] = A(TARGETS);
x11.utf8 = x11.XInternAtom(dpy, "UTF8_STRING", False);
supported[count++] = x11.targets;
supported[count++] = XA_STRING; supported[count++] = XA_STRING;
if (x11.utf8) if (A(UTF8_STRING))
supported[count++] = x11.utf8; supported[count++] = A(UTF8_STRING);
x11.XChangeProperty(dpy, req->requestor, req->property, XA_ATOM, 32, PropModeReplace, (unsigned char *)supported, count); x11.XChangeProperty(dpy, req->requestor, req->property, XA_ATOM, 32, PropModeReplace, (unsigned char *)supported, count);
respond.xselection.property=req->property; respond.xselection.property=req->property;
} }
...@@ -1867,10 +2073,12 @@ void x11_event_thread(void *args) ...@@ -1867,10 +2073,12 @@ void x11_event_thread(void *args)
break; break;
case X11_LOCAL_SETNAME: case X11_LOCAL_SETNAME:
x11.XSetIconName(dpy, win, lev.data.name); x11.XSetIconName(dpy, win, lev.data.name);
set_win_property(A(_NET_WM_ICON_NAME), A(UTF8_STRING), 8, PropModeReplace, lev.data.name, strlen(lev.data.name));
x11.XFlush(dpy); x11.XFlush(dpy);
break; break;
case X11_LOCAL_SETTITLE: case X11_LOCAL_SETTITLE:
x11.XStoreName(dpy, win, lev.data.title); x11.XStoreName(dpy, win, lev.data.title);
set_win_property(A(_NET_WM_NAME), A(UTF8_STRING), 8, PropModeReplace, lev.data.name, strlen(lev.data.name));
x11.XFlush(dpy); x11.XFlush(dpy);
break; break;
case X11_LOCAL_COPY: case X11_LOCAL_COPY:
...@@ -1895,7 +2103,7 @@ void x11_event_thread(void *args) ...@@ -1895,7 +2103,7 @@ void x11_event_thread(void *args)
FREE_AND_NULL(pastebuf); FREE_AND_NULL(pastebuf);
} }
else if(sowner!=None) { else if(sowner!=None) {
x11.XConvertSelection(dpy, CONSOLE_CLIPBOARD, x11.utf8 ? x11.utf8 : XA_STRING, x11.utf8 ? x11.utf8 : XA_STRING, win, CurrentTime); x11.XConvertSelection(dpy, CONSOLE_CLIPBOARD, A(UTF8_STRING) ? A(UTF8_STRING) : XA_STRING, A(UTF8_STRING) ? A(UTF8_STRING) : XA_STRING, win, CurrentTime);
} }
else { else {
/* Set paste buffer */ /* Set paste buffer */
...@@ -1915,12 +2123,10 @@ void x11_event_thread(void *args) ...@@ -1915,12 +2123,10 @@ void x11_event_thread(void *args)
x11.XBell(dpy, 100); x11.XBell(dpy, 100);
break; break;
case X11_LOCAL_SETICON: { case X11_LOCAL_SETICON: {
Atom wmicon = x11.XInternAtom(dpy, "_NET_WM_ICON", False); // TODO: set_icon() is obsolete... delete
if (wmicon) {
x11.XChangeProperty(dpy, win, wmicon, XA_CARDINAL, 32, PropModeReplace, (unsigned char *)lev.data.icon_data, lev.data.icon_data[0] * lev.data.icon_data[1] + 2);
x11.XFlush(dpy);
}
set_icon(&lev.data.icon_data[2], lev.data.icon_data[0], NULL); set_icon(&lev.data.icon_data[2], lev.data.icon_data[0], NULL);
set_win_property(A(_NET_WM_ICON), XA_CARDINAL, 32, PropModeReplace, lev.data.icon_data, lev.data.icon_data[0] * lev.data.icon_data[1] + 2);
x11.XFlush(dpy);
free(lev.data.icon_data); free(lev.data.icon_data);
break; break;
} }
......
...@@ -143,9 +143,6 @@ struct x11 { ...@@ -143,9 +143,6 @@ struct x11 {
void (*XRRFreeCrtcInfo)(XRRCrtcInfo *crtcInfo); void (*XRRFreeCrtcInfo)(XRRCrtcInfo *crtcInfo);
void (*XRRFreeScreenResources)(XRRScreenResources *resources); void (*XRRFreeScreenResources)(XRRScreenResources *resources);
#endif #endif
Atom utf8;
Atom targets;
Atom workarea;
}; };
extern int local_pipe[2]; /* Used for passing local events */ extern int local_pipe[2]; /* Used for passing local events */
...@@ -159,11 +156,8 @@ extern char *pastebuf; ...@@ -159,11 +156,8 @@ extern char *pastebuf;
extern sem_t pastebuf_set; extern sem_t pastebuf_set;
extern sem_t pastebuf_used; extern sem_t pastebuf_used;
extern Atom copybuf_format; extern Atom copybuf_format;
extern Atom pastebuf_format;
extern sem_t init_complete; extern sem_t init_complete;
extern sem_t mode_set; extern sem_t mode_set;
extern sem_t event_thread_complete;
extern int terminate;
extern int x11_window_xpos; extern int x11_window_xpos;
extern int x11_window_ypos; extern int x11_window_ypos;
extern int x11_initialized; extern int x11_initialized;
......
...@@ -1723,6 +1723,7 @@ main(int argc, char **argv) ...@@ -1723,6 +1723,7 @@ main(int argc, char **argv)
#endif #endif
if (initciolib(ciolib_mode)) if (initciolib(ciolib_mode))
return 1; return 1;
setname("SyncTERM");
if (settings.blocky) if (settings.blocky)
cio_api.options |= CONIO_OPT_BLOCKY_SCALING; cio_api.options |= CONIO_OPT_BLOCKY_SCALING;
else else
......
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Please register or to comment