Replaced X event notifying via add_fd(). Now all X events could be reported

without possible stealing from fltk. Prevous, add_handler(), would send only
unknown events for fltk which leave us without really important ones, like selection events
used by XSETTINGS manager.

Added XSETTINGS support (yet unfinished) which will make evoke as XSETTINGS manager.
This commit is contained in:
Sanel Zukan
2007-09-18 14:06:09 +00:00
parent 00f5f2d59a
commit ad69c2fc2c
7 changed files with 265 additions and 11 deletions

154
evoke/Xsm.cpp Normal file
View File

@ -0,0 +1,154 @@
/*
* $Id$
*
* Evoke, head honcho of everything
* Part of Equinox Desktop Environment (EDE).
* Copyright (c) 2000-2007 EDE Authors.
*
* This program is licensed under terms of the
* GNU General Public License version 2 or newer.
* See COPYING for details.
*/
#include "Xsm.h"
#include <edelib/Debug.h>
#include <FL/x.h>
#include <stdio.h> // snprintf
struct XsmData {
Window window;
Atom manager_atom;
Atom selection_atom;
Atom xsettings_atom;
unsigned long serial;
};
struct XsettingsColor {
unsigned char red, green, blue, alpha;
};
struct XsettingsSetting {
char* name;
XsettingsType type;
union {
int v_int;
char* v_string;
XsettingsColor v_color;
} data;
unsigned long last_changed_serial;
};
struct TimeStampInfo {
Window window;
Atom timestamp_prop_atom;
};
// Bool (X type) is used since this function is going to XIfEvent()
Bool timestamp_predicate(Display* dpy, XEvent* xev, XPointer arg) {
TimeStampInfo* info = (TimeStampInfo*)arg;
if(xev->type == PropertyNotify &&
xev->xproperty.window == info->window &&
xev->xproperty.atom == info->timestamp_prop_atom) {
return True;
}
return False;
}
Time get_server_time(Display* dpy, Window win) {
unsigned char c = 'a';
TimeStampInfo info;
XEvent xev;
info.timestamp_prop_atom = XInternAtom(dpy, "_TIMESTAMP_PROP", False);
info.window = win;
XChangeProperty(dpy, win, info.timestamp_prop_atom, info.timestamp_prop_atom,
8, PropModeReplace, &c, 1);
XIfEvent(dpy, &xev, timestamp_predicate, (XPointer)&info);
return xev.xproperty.time;
}
Xsm::Xsm() : data(NULL) { }
Xsm::~Xsm() {
if(data) {
XDestroyWindow(fl_display, data->window);
delete data;
}
puts("Xsm::~Xsm()");
}
bool Xsm::is_running(void) {
char buff[256];
snprintf(buff, sizeof(buff)-1, "_XSETTINGS_S%d", fl_screen);
Atom selection = XInternAtom(fl_display, buff, False);
if(XGetSelectionOwner(fl_display, selection))
return true;
return false;
}
bool Xsm::init(void) {
char buff[256];
data = new XsmData;
snprintf(buff, sizeof(buff)-1, "_XSETTINGS_S%d", fl_screen);
data->selection_atom = XInternAtom(fl_display, buff, False);
data->xsettings_atom = XInternAtom(fl_display, "_XSETTINGS_SETTINGS", False);
data->manager_atom = XInternAtom(fl_display, "MANAGER", False);
data->serial = 0;
data->window = XCreateSimpleWindow(fl_display, RootWindow(fl_display, fl_screen),
0, 0, 10, 10, 0, WhitePixel(fl_display, fl_screen), WhitePixel(fl_display, fl_screen));
XSelectInput(fl_display, data->window, PropertyChangeMask);
Time timestamp = get_server_time(fl_display, data->window);
XSetSelectionOwner(fl_display, data->selection_atom, data->window, timestamp);
// check if we got ownership
if(XGetSelectionOwner(fl_display, data->selection_atom) == data->window) {
XClientMessageEvent xev;
xev.type = ClientMessage;
xev.window = RootWindow(fl_display, fl_screen);
xev.message_type = data->manager_atom;
xev.format = 32;
xev.data.l[0] = timestamp;
xev.data.l[1] = data->selection_atom;
xev.data.l[2] = data->window;
xev.data.l[3] = 0; // manager specific data
xev.data.l[4] = 0; // manager specific data
XSendEvent(fl_display, RootWindow(fl_display, fl_screen), False, StructureNotifyMask, (XEvent*)&xev);
return true;
}
return false;
}
bool Xsm::should_quit(const XEvent* xev) {
EASSERT(data != NULL);
if(xev->xany.window == data->window &&
xev->xany.type == SelectionClear &&
xev->xselectionclear.selection == data->selection_atom) {
puts("XXXXXXXXXXXXX");
return true;
}
return false;
}