static void selclear(XEvent* evnt);
static void selnotify(XEvent* evnt);
static void selrequest(XEvent* evnt);
+static void propnotify(XEvent* evnt);
struct XFont {
struct {
unsigned depth;
int screen;
/* assume a single window for now. these are its attributes */
- Window window;
+ Window self;
XftDraw* xft;
Pixmap pixmap;
int width;
X.colormap = wa.colormap;
X.screen = DefaultScreen(X.display);
X.depth = DefaultDepth(X.display, X.screen);
+
/* initialize selection atoms */
for (int i = 0; i < (sizeof(Selections) / sizeof(Selections[0])); i++)
Selections[i].atom = XInternAtom(X.display, Selections[i].name, 0);
X.height = height;
XWindowAttributes wa;
XGetWindowAttributes(X.display, X.root, &wa);
- X.window = XCreateSimpleWindow(X.display, X.root,
+ X.self = XCreateSimpleWindow(X.display, X.root,
(wa.width - X.width) / 2,
(wa.height - X.height) /2,
X.width,
/* register interest in the delete window message */
Atom wmDeleteMessage = XInternAtom(X.display, "WM_DELETE_WINDOW", False);
- XSetWMProtocols(X.display, X.window, &wmDeleteMessage, 1);
+ XSetWMProtocols(X.display, X.self, &wmDeleteMessage, 1);
/* setup window attributes and events */
XSetWindowAttributes swa;
swa.backing_store = WhenMapped;
swa.bit_gravity = NorthWestGravity;
- XChangeWindowAttributes(X.display, X.window, CWBackingStore|CWBitGravity, &swa);
- XStoreName(X.display, X.window, name);
- XSelectInput(X.display, X.window,
+ XChangeWindowAttributes(X.display, X.self, CWBackingStore|CWBitGravity, &swa);
+ XStoreName(X.display, X.self, name);
+ XSelectInput(X.display, X.root, PropertyChangeMask);
+ XSelectInput(X.display, X.self,
StructureNotifyMask
| ButtonPressMask
| ButtonReleaseMask
/* set input methods */
if ((X.xim = XOpenIM(X.display, 0, 0, 0)))
- X.xic = XCreateIC(X.xim, XNInputStyle, XIMPreeditNothing|XIMStatusNothing, XNClientWindow, X.window, XNFocusWindow, X.window, NULL);
+ X.xic = XCreateIC(X.xim, XNInputStyle, XIMPreeditNothing|XIMStatusNothing, XNClientWindow, X.self, XNFocusWindow, X.self, NULL);
/* initialize pixmap and drawing context */
- X.pixmap = XCreatePixmap(X.display, X.window, width, height, X.depth);
+ X.pixmap = XCreatePixmap(X.display, X.self, width, height, X.depth);
X.xft = XftDrawCreate(X.display, X.pixmap, X.visual, X.colormap);
/* initialize the graphics context */
XGCValues gcv;
gcv.foreground = WhitePixel(X.display, X.screen);
gcv.graphics_exposures = False;
- X.gc = XCreateGC(X.display, X.window, GCForeground|GCGraphicsExposures, &gcv);
+ X.gc = XCreateGC(X.display, X.self, GCForeground|GCGraphicsExposures, &gcv);
+
+ /* Create and updtate tide-specific properties */
+ Atom prop = XInternAtom(X.display, "TIDE_WINDOWS", False);
+ XChangeProperty(X.display, X.root, prop, XA_WINDOW, 32, PropModeAppend, (unsigned char*)&X.self, 1);
+ prop = XInternAtom(X.display, "TIDE_COMM", False);
+ XChangeProperty(X.display, X.self, prop, XA_STRING, 8, PropModeReplace, "", 0);
}
void x11_dialog(char* name, int height, int width) {
x11_window(name, height, width);
Atom WindowType = XInternAtom(X.display, "_NET_WM_WINDOW_TYPE", False);
Atom DialogType = XInternAtom(X.display, "_NET_WM_WINDOW_TYPE_DIALOG", False);
- XChangeProperty(X.display, X.window, WindowType, XA_ATOM, 32, PropModeReplace, (unsigned char*)&DialogType, 1);
+ XChangeProperty(X.display, X.self, WindowType, XA_ATOM, 32, PropModeReplace, (unsigned char*)&DialogType, 1);
}
void x11_show(void) {
ce.type = ConfigureNotify;
ce.width = X.width;
ce.height = X.height;
- XSendEvent(X.display, X.window, False, StructureNotifyMask, (XEvent *)&ce);
- XMapWindow(X.display, X.window);
+ XSendEvent(X.display, X.self, False, StructureNotifyMask, (XEvent *)&ce);
+ XMapWindow(X.display, X.self);
}
bool x11_running(void) {
void x11_flip(void) {
Config->redraw(X.width, X.height);
- XCopyArea(X.display, X.pixmap, X.window, X.gc, 0, 0, X.width, X.height, 0, 0);
+ XCopyArea(X.display, X.pixmap, X.self, X.gc, 0, 0, X.width, X.height, 0, 0);
x11_flush();
}
case SelectionClear: selclear(e); break;
case SelectionNotify: selnotify(e); break;
case SelectionRequest: selrequest(e); break;
+ case PropertyNotify: propnotify(e); break;
case ClientMessage:
if (e->xclient.data.l[0] == wmDeleteMessage)
Config->shutdown();
if (e->xconfigure.width != X.width || e->xconfigure.height != X.height) {
X.width = e->xconfigure.width;
X.height = e->xconfigure.height;
- X.pixmap = XCreatePixmap(X.display, X.window, X.width, X.height, X.depth);
+ X.pixmap = XCreatePixmap(X.display, X.self, X.width, X.height, X.depth);
X.xft = XftDrawCreate(X.display, X.pixmap, X.visual, X.colormap);
}
break;
void x11_events_take(void) {
XEvent e;
int nevents;
- XGetMotionEvents(X.display, X.window, CurrentTime, CurrentTime, &nevents);
+ XGetMotionEvents(X.display, X.self, CurrentTime, CurrentTime, &nevents);
while (XPending(X.display)) {
XNextEvent(X.display, &e);
if (!XFilterEvent(&e, None))
}
void x11_mouse_set(int x, int y) {
- XWarpPointer(X.display, X.window, X.window, 0, 0, X.width, X.height, x, y);
+ XWarpPointer(X.display, X.self, X.self, 0, 0, X.width, X.height, x, y);
}
void x11_mouse_get(int* ptrx, int* ptry) {
Window xw; int x; unsigned int ux;
- XQueryPointer(X.display, X.window, &xw, &xw, &x, &x, ptrx, ptry, &ux);
+ XQueryPointer(X.display, X.self, &xw, &xw, &x, &x, ptrx, ptry, &ux);
}
XFont x11_font_load(char* name) {
/* Selection Handling
*****************************************************************************/
-
static char* readprop(Display* disp, Window win, Atom prop) {
Atom type;
int format;
if (evnt->xselection.property == None)
return;
struct XSel* sel = selfetch( evnt->xselection.selection );
- char* propdata = readprop(X.display, X.window, sel->atom);
+ char* propdata = readprop(X.display, X.self, sel->atom);
if (evnt->xselection.target == SelTarget) {
void(*cbfn)(char*) = sel->callback;
sel->callback = NULL;
struct XSel* sel = &(Selections[selid]);
if (sel->callback) return false;
Window owner = XGetSelectionOwner(X.display, sel->atom);
- if (owner == X.window) {
+ if (owner == X.self) {
cbfn(sel->text);
} else if (owner != None){
sel->callback = cbfn;
- XConvertSelection(X.display, sel->atom, SelTarget, sel->atom, X.window, CurrentTime);
+ XConvertSelection(X.display, sel->atom, SelTarget, sel->atom, X.self, CurrentTime);
}
return true;
}
return false;
} else {
sel->text = str;
- XSetSelectionOwner(X.display, sel->atom, X.window, CurrentTime);
+ XSetSelectionOwner(X.display, sel->atom, X.self, CurrentTime);
return true;
}
}
+
+/* Tide Server Communication
+ *****************************************************************************/
+static void propnotify(XEvent* evnt) {
+}
--- /dev/null
+#include <stdc.h>
+#include <utf.h>
+#include <edit.h>
+#include <X11/Xlib.h>
+#include <X11/Xatom.h>
+#include <X11/Xft/Xft.h>
+#include <unistd.h>
+
+struct {
+ Display* display;
+ Window root;
+ Window self;
+} X;
+
+static void* prop_get(Window win, char* propname, Atom type, unsigned long* nitems);
+static void prop_set(Window win, char* propname, Atom type, int format, void* items, unsigned long nitems);
+
+/* Main Routine
+ ******************************************************************************/
+int main(int argc, char** argv) {
+ if (!(X.display = XOpenDisplay(0)))
+ die("could not open display");
+ X.root = DefaultRootWindow(X.display);
+ X.self = XCreateSimpleWindow(X.display, X.root, 0, 0, 1, 1, 0, 0, 0);
+
+ XGrabServer(X.display);
+ unsigned long nwindows = 0;
+ Window* windows = prop_get(X.root, "TIDE_WINDOWS", XA_WINDOW, &nwindows);
+ printf("Windows: %lu\n", nwindows);
+ XUngrabServer(X.display);
+
+ return 0;
+}
+
+static void* prop_get(Window win, char* propname, Atom type, unsigned long* nitems) {
+ Atom rtype, prop = XInternAtom(X.display, propname, False);
+ unsigned long rformat = 0, nleft = 0;
+ unsigned char* data = NULL;
+ XGetWindowProperty(X.display, win, prop, 0, -1, False, type, &rtype,
+ (int*)&rformat, nitems, &nleft, &data);
+ if (rtype != type)
+ data = NULL, *nitems = 0;
+ return data;
+}
+
+static void prop_set(Window win, char* propname, Atom type, int format, void* items, unsigned long nitems) {
+ Atom prop = XInternAtom(X.display, propname, False);
+ XChangeProperty(X.display, win, prop, type, format, PropModeReplace, items, (int)nitems);
+}