diff --git a/cfg/checks/x11.mk b/cfg/checks/x11.mk
index ba36831..b5b2ed9 100644
--- a/cfg/checks/x11.mk
+++ b/cfg/checks/x11.mk
@@ -1,7 +1,7 @@
# Variables for X11 support
X11_LIBS = x11
X11_CFLAGS = -DX11
-X11_OBJ = xtra.o
+X11_OBJ = x11focus.o
# Check if we can build X11 support
CHECK_X11_LIBS = $(shell $(PKG_CONFIG) --exists $(X11_LIBS) || echo -n "error")
diff --git a/src/notify.c b/src/notify.c
index 6298783..c8b2ed8 100644
--- a/src/notify.c
+++ b/src/notify.c
@@ -35,7 +35,7 @@
#include "misc_tools.h"
#include "notify.h"
#include "settings.h"
-#include "xtra.h"
+#include "x11focus.h"
#if defined(AUDIO) || defined(SOUND_NOTIFY)
#ifdef __APPLE__
diff --git a/src/toxic.c b/src/toxic.c
index 92c0321..0d88527 100644
--- a/src/toxic.c
+++ b/src/toxic.c
@@ -66,7 +66,7 @@
#include "windows.h"
#ifdef X11
-#include "xtra.h"
+#include "x11focus.h"
#endif
#ifdef AUDIO
@@ -205,10 +205,7 @@ void exit_toxic_success(Tox *m)
curl_global_cleanup();
#ifdef X11
- /* We have to terminate xtra last coz reasons
- * Please don't call this anywhere else coz trust me
- */
- terminate_xtra();
+ terminate_x11focus();
#endif /* X11 */
exit(EXIT_SUCCESS);
@@ -1350,21 +1347,6 @@ static void init_default_data_files(void)
free(user_config_dir);
}
-// this doesn't do anything (yet)
-#ifdef X11
-void DnD_callback(const char *asdv, DropType dt)
-{
- UNUSED_VAR(asdv);
- UNUSED_VAR(dt);
- // if (dt != DT_plain)
- // return;
-
- // pthread_mutex_lock(&Winthread.lock);
- // line_info_add(prompt, NULL, NULL, NULL, SYS_MSG, 0, 0, asdv);
- // pthread_mutex_unlock(&Winthread.lock);
-}
-#endif /* X11 */
-
int main(int argc, char **argv)
{
/* Make sure all written files are read/writeable only by the current user. */
@@ -1422,7 +1404,7 @@ int main(int argc, char **argv)
#ifdef X11
- if (init_xtra(DnD_callback) == -1) {
+ if (init_x11focus() == -1) {
queue_init_message("X failed to initialize");
}
diff --git a/src/x11focus.c b/src/x11focus.c
new file mode 100644
index 0000000..0c4b1af
--- /dev/null
+++ b/src/x11focus.c
@@ -0,0 +1,87 @@
+/* x11focus.c
+ *
+ *
+ * Copyright (C) 2020 Toxic All Rights Reserved.
+ *
+ * This file is part of Toxic.
+ *
+ * Toxic is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * Toxic is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with Toxic. If not, see .
+ *
+ */
+
+#include "x11focus.h"
+
+#ifndef __APPLE__
+
+#include
+
+static struct Focus {
+ Display *display;
+ Window terminal_window;
+} Focus;
+
+static long unsigned int focused_window_id(void)
+{
+ if (!Focus.display) {
+ return 0;
+ }
+
+ Window focus;
+ int revert;
+
+ XLockDisplay(Focus.display);
+ XGetInputFocus(Focus.display, &focus, &revert);
+ XUnlockDisplay(Focus.display);
+
+ return focus;
+}
+
+bool is_focused(void)
+{
+ if (!Focus.display) {
+ return false;
+ }
+
+ return Focus.terminal_window == focused_window_id();
+}
+
+int init_x11focus(void)
+{
+ if (XInitThreads() == 0) {
+ return -1;
+ }
+
+ Focus.display = XOpenDisplay(NULL);
+
+ if (!Focus.display) {
+ return -1;
+ }
+
+ Focus.terminal_window = focused_window_id();
+
+ return 0;
+}
+
+void terminate_x11focus(void)
+{
+ if (!Focus.display || !Focus.terminal_window) {
+ return;
+ }
+
+ XLockDisplay(Focus.display);
+ XCloseDisplay(Focus.display);
+ XUnlockDisplay(Focus.display);
+}
+
+#endif /* !__APPLE__ */
diff --git a/src/xtra.h b/src/x11focus.h
similarity index 67%
rename from src/xtra.h
rename to src/x11focus.h
index 7b423af..565168d 100644
--- a/src/xtra.h
+++ b/src/x11focus.h
@@ -1,7 +1,7 @@
/* xtra.h
*
*
- * Copyright (C) 2014 Toxic All Rights Reserved.
+ * Copyright (C) 2020 Toxic All Rights Reserved.
*
* This file is part of Toxic.
*
@@ -20,21 +20,15 @@
*
*/
-#ifndef XTRA_H
-#define XTRA_H
+#ifndef X11FOCUS_H
+#define X11FOCUS_H
+
+#include
/* NOTE: If no xlib present don't compile */
-typedef enum {
- DT_plain,
- DT_file_list
-}
-DropType;
+int init_x11focus(void);
+void terminate_x11focus(void);
+bool is_focused(void);
-typedef void (*drop_callback)(const char *, DropType);
-
-int init_xtra(drop_callback d);
-void terminate_xtra(void);
-int is_focused(void); /* returns bool */
-
-#endif /* XTRA_H */
+#endif /* X11FOCUS */
diff --git a/src/xtra.c b/src/xtra.c
deleted file mode 100644
index 6a3e890..0000000
--- a/src/xtra.c
+++ /dev/null
@@ -1,426 +0,0 @@
-/* xtra.c
- *
- *
- * Copyright (C) 2014 Toxic All Rights Reserved.
- *
- * This file is part of Toxic.
- *
- * Toxic is free software: you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation, either version 3 of the License, or
- * (at your option) any later version.
- *
- * Toxic is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with Toxic. If not, see .
- *
- */
-
-#include "misc_tools.h"
-#include "xtra.h"
-
-#ifndef __APPLE__
-
-#include
-#include
-
-#include
-#include
-#include
-#include
-#include
-
-
-const Atom XtraTerminate = 1;
-const Atom XtraNil = 0;
-
-static Atom XdndAware;
-static Atom XdndEnter;
-static Atom XdndLeave;
-static Atom XdndPosition;
-static Atom XdndStatus;
-static Atom XdndDrop;
-static Atom XdndSelection;
-static Atom XdndDATA;
-static Atom XdndTypeList;
-static Atom XdndActionCopy;
-static Atom XdndFinished;
-
-struct Xtra {
- drop_callback on_drop;
- Display *display;
- Window terminal_window;
- Window proxy_window;
- Window source_window; /* When we have a drop */
- Atom handling_version;
- Atom expecting_type;
-} Xtra;
-
-typedef struct Property {
- unsigned char *data;
- int read_format;
- unsigned long read_num;
- Atom read_type;
-} Property;
-
-static Property read_property(Window s, Atom p)
-{
- Atom read_type;
- int read_format;
- unsigned long read_num;
- unsigned long left_bytes;
- unsigned char *data = NULL;
-
- int read_bytes = 1024;
-
- /* Keep trying to read the property until there are no bytes unread */
- do {
- if (data) {
- XFree(data);
- }
-
- XGetWindowProperty(Xtra.display, s,
- p, 0,
- read_bytes,
- False, AnyPropertyType,
- &read_type, &read_format,
- &read_num, &left_bytes,
- &data);
-
- read_bytes *= 2;
- } while (left_bytes != 0);
-
- Property property = {data, read_format, read_num, read_type};
- return property;
-}
-
-static Atom get_dnd_type(long *a, int l)
-{
- int i = 0;
-
- for (; i < l; i ++) {
- if (a[i] != XtraNil) {
- return a[i]; /* Get first valid */
- }
- }
-
- return XtraNil;
-}
-
-/* TODO maybe support only certain types in the future */
-static void handle_xdnd_enter(XClientMessageEvent *e)
-{
- Xtra.handling_version = (e->data.l[1] >> 24);
-
- if ((e->data.l[1] & 1)) {
- // Fetch the list of possible conversions
- Property p = read_property(e->data.l[0], XdndTypeList);
- Xtra.expecting_type = get_dnd_type((long *)p.data, p.read_num);
- XFree(p.data);
- } else {
- // Use the available list
- Xtra.expecting_type = get_dnd_type(e->data.l + 2, 3);
- }
-}
-
-static void handle_xdnd_position(XClientMessageEvent *e)
-{
- XEvent ev = {
- .xclient = {
- .type = ClientMessage,
- .display = e->display,
- .window = e->data.l[0],
- .message_type = XdndStatus,
- .format = 32,
- .data = {
- .l = {
- Xtra.proxy_window,
- (Xtra.expecting_type != XtraNil),
- 0, 0,
- XdndActionCopy
- }
- }
- }
- };
-
- XSendEvent(Xtra.display, e->data.l[0], False, NoEventMask, &ev);
- XFlush(Xtra.display);
-}
-
-static void handle_xdnd_drop(XClientMessageEvent *e)
-{
- /* Not expecting any type */
- if (Xtra.expecting_type == XtraNil) {
- XEvent ev = {
- .xclient = {
- .type = ClientMessage,
- .display = e->display,
- .window = e->data.l[0],
- .message_type = XdndFinished,
- .format = 32,
- .data = {
- .l = {Xtra.proxy_window, 0, 0}
- }
- }
- };
-
- XSendEvent(Xtra.display, e->data.l[0], False, NoEventMask, &ev);
- } else {
- Xtra.source_window = e->data.l[0];
- XConvertSelection(Xtra.display,
- XdndSelection,
- Xtra.expecting_type,
- XdndSelection,
- Xtra.proxy_window,
- Xtra.handling_version >= 1 ? e->data.l[2] : CurrentTime);
- }
-}
-
-static void handle_xdnd_selection(XSelectionEvent *e)
-{
- UNUSED_VAR(e);
-
- /* DnD succesfully finished, send finished and call callback */
- XEvent ev = {
- .xclient = {
- .type = ClientMessage,
- .display = Xtra.display,
- .window = Xtra.source_window,
- .message_type = XdndFinished,
- .format = 32,
- .data = {
- .l = {Xtra.proxy_window, 1, XdndActionCopy}
- }
- }
- };
- XSendEvent(Xtra.display, Xtra.source_window, False, NoEventMask, &ev);
-
- Property p = read_property(Xtra.proxy_window, XdndSelection);
- DropType dt;
-
- if (strcmp(XGetAtomName(Xtra.display, p.read_type), "text/uri-list") == 0) {
- dt = DT_file_list;
- } else { /* text/uri-list */
- dt = DT_plain;
- }
-
-
- /* Call callback for every entry */
- if (Xtra.on_drop && p.read_num) {
- char *sptr;
- char *str = strtok_r((char *) p.data, "\n\r", &sptr);
-
- if (str) {
- Xtra.on_drop(str, dt);
- }
-
- while ((str = strtok_r(NULL, "\n\r", &sptr))) {
- Xtra.on_drop(str, dt);
- }
- }
-
- if (p.data) {
- XFree(p.data);
- }
-}
-
-void *event_loop(void *p)
-{
- /* Handle events like a real nigga */
-
- UNUSED_VAR(p); /* DINDUNOTHIN */
-
- XEvent event;
-
- while (Xtra.display) {
- /* NEEDMOEVENTSFODEMPROGRAMS */
-
- int pending = 0;
-
- XLockDisplay(Xtra.display);
-
- if ((pending = XPending(Xtra.display))) {
- XNextEvent(Xtra.display, &event);
- }
-
- if (!pending) {
- XUnlockDisplay(Xtra.display);
- sleep_thread(10000L);
- continue;
- }
-
- if (event.type == ClientMessage) {
- Atom type = event.xclient.message_type;
-
- if (type == XdndEnter) {
- handle_xdnd_enter(&event.xclient);
- } else if (type == XdndPosition) {
- handle_xdnd_position(&event.xclient);
- } else if (type == XdndDrop) {
- handle_xdnd_drop(&event.xclient);
- } else if (type == XtraTerminate) {
- break;
- }
- } else if (event.type == SelectionNotify) {
- handle_xdnd_selection(&event.xselection);
- }
- /* AINNOBODYCANHANDLEDEMEVENTS*/
- else {
- XSendEvent(Xtra.display, Xtra.terminal_window, 0, 0, &event);
- }
-
- XUnlockDisplay(Xtra.display);
- }
-
- /* Actual XTRA termination
- * Please call xtra_terminate() at exit
- * otherwise HEWUSAGUDBOI happens
- */
- if (Xtra.display) {
- XCloseDisplay(Xtra.display);
- }
-
- return (Xtra.display = NULL);
-}
-
-static long unsigned int focused_window_id(void)
-{
- if (!Xtra.display) {
- return 0;
- }
-
- Window focus;
- int revert;
- XLockDisplay(Xtra.display);
- XGetInputFocus(Xtra.display, &focus, &revert);
- XUnlockDisplay(Xtra.display);
- return focus;
-}
-
-int is_focused(void)
-{
- return Xtra.display && (Xtra.proxy_window == focused_window_id() || Xtra.terminal_window == focused_window_id());
-}
-
-int init_xtra(drop_callback d)
-{
- if (!d) {
- return -1;
- } else {
- Xtra.on_drop = d;
- }
-
- XInitThreads();
-
- if (!(Xtra.display = XOpenDisplay(NULL))) {
- return -1;
- }
-
- Xtra.terminal_window = focused_window_id();
-
- /* OSX: if focused window is 0, it means toxic is ran from
- * native terminal and not X11 terminal window, silently exit */
- if (!Xtra.terminal_window) {
- return 0;
- }
-
- {
- /* Create an invisible window which will act as proxy for the DnD operation. */
- XSetWindowAttributes attr = {0};
- attr.event_mask = EnterWindowMask |
- LeaveWindowMask |
- ButtonMotionMask |
- ButtonPressMask |
- ButtonReleaseMask |
- ResizeRedirectMask;
-
- attr.do_not_propagate_mask = NoEventMask;
-
- Window root;
- int x, y;
- unsigned int wht, hht, b, d;
-
- /* Since we cannot capture resize events for parent window we will have to create
- * this window to have maximum size as defined in root window
- */
- XGetGeometry(Xtra.display,
- XDefaultRootWindow(Xtra.display),
- &root, &x, &y, &wht, &hht, &b, &d);
-
- if (!(Xtra.proxy_window = XCreateWindow
- (Xtra.display, Xtra.terminal_window, /* Parent */
- 0, 0, /* Position */
- wht, hht, /* Width + height */
- 0, /* Border width */
- CopyFromParent, /* Depth */
- InputOnly, /* Class */
- CopyFromParent, /* Visual */
- CWEventMask | CWCursor, /* Value mask */
- &attr))) { /* Attributes for value mask */
- return -1;
- }
- }
-
- XMapWindow(Xtra.display, Xtra.proxy_window); /* Show window (sandwich) */
- XLowerWindow(Xtra.display, Xtra.proxy_window); /* Don't interfere with parent lmao */
-
- XdndAware = XInternAtom(Xtra.display, "XdndAware", False);
- XdndEnter = XInternAtom(Xtra.display, "XdndEnter", False);
- XdndLeave = XInternAtom(Xtra.display, "XdndLeave", False);
- XdndPosition = XInternAtom(Xtra.display, "XdndPosition", False);
- XdndStatus = XInternAtom(Xtra.display, "XdndStatus", False);
- XdndDrop = XInternAtom(Xtra.display, "XdndDrop", False);
- XdndSelection = XInternAtom(Xtra.display, "XdndSelection", False);
- XdndDATA = XInternAtom(Xtra.display, "XdndDATA", False);
- XdndTypeList = XInternAtom(Xtra.display, "XdndTypeList", False);
- XdndActionCopy = XInternAtom(Xtra.display, "XdndActionCopy", False);
- XdndFinished = XInternAtom(Xtra.display, "XdndFinished", False);
-
- /* Inform my nigga windows that we are aware of dnd */
- Atom XdndVersion = 3;
- XChangeProperty(Xtra.display,
- Xtra.proxy_window,
- XdndAware,
- XA_ATOM,
- 32,
- PropModeReplace,
- (unsigned char *)&XdndVersion, 1);
-
- pthread_t id;
-
- if (pthread_create(&id, NULL, event_loop, NULL) != 0) {
- return -1;
- }
-
- pthread_detach(id);
-
- return 0;
-}
-
-void terminate_xtra(void)
-{
- if (!Xtra.display || !Xtra.terminal_window) {
- return;
- }
-
- XEvent terminate = {
- .xclient = {
- .type = ClientMessage,
- .display = Xtra.display,
- .message_type = XtraTerminate,
- }
- };
-
- XLockDisplay(Xtra.display);
- XDeleteProperty(Xtra.display, Xtra.proxy_window, XdndAware);
- XSendEvent(Xtra.display, Xtra.proxy_window, 0, NoEventMask, &terminate);
- XUnlockDisplay(Xtra.display);
-
- while (Xtra.display); /* Wait for termination */
-}
-
-#endif /* !__APPLE__ */