mirror of
https://github.com/edeproject/ede.git
synced 2023-08-10 21:13:03 +03:00
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:
@ -19,7 +19,7 @@
|
||||
#include "Autostart.h"
|
||||
|
||||
#include <edelib/File.h>
|
||||
#include <edelib/Regex.h>
|
||||
//#include <edelib/Regex.h>
|
||||
#include <edelib/Config.h>
|
||||
#include <edelib/DesktopFile.h>
|
||||
#include <edelib/Directory.h>
|
||||
@ -195,14 +195,17 @@ void service_watcher_cb(int pid, int signum) {
|
||||
EvokeService::instance()->service_watcher(pid, signum);
|
||||
}
|
||||
|
||||
EvokeService::EvokeService() : is_running(0), logfile(NULL), pidfile(NULL), lockfile(NULL) {
|
||||
top_win = NULL;
|
||||
EvokeService::EvokeService() :
|
||||
is_running(0), logfile(NULL), xsm(NULL), pidfile(NULL), lockfile(NULL), top_win(NULL) {
|
||||
}
|
||||
|
||||
EvokeService::~EvokeService() {
|
||||
if(logfile)
|
||||
delete logfile;
|
||||
|
||||
if(xsm)
|
||||
delete xsm;
|
||||
|
||||
if(lockfile) {
|
||||
edelib::file_remove(lockfile);
|
||||
free(lockfile);
|
||||
@ -434,6 +437,30 @@ void EvokeService::init_autostart(bool safe) {
|
||||
dlg.run();
|
||||
}
|
||||
|
||||
void EvokeService::init_xsettings_manager(void) {
|
||||
xsm = new Xsm;
|
||||
|
||||
if(xsm->is_running()) {
|
||||
int ret = edelib::ask(_("XSETTINGS manager already running on this screen. Would you like to replace it?"));
|
||||
if(ret < 1) {
|
||||
stop_xsettings_manager();
|
||||
return;
|
||||
} else
|
||||
goto do_it;
|
||||
}
|
||||
|
||||
do_it:
|
||||
if(!xsm->init()) {
|
||||
edelib::alert(_("Unable to load XSETTINGS manager properly"));
|
||||
stop_xsettings_manager();
|
||||
}
|
||||
}
|
||||
|
||||
void EvokeService::stop_xsettings_manager(void) {
|
||||
delete xsm;
|
||||
xsm = NULL;
|
||||
}
|
||||
|
||||
void EvokeService::setup_atoms(Display* d) {
|
||||
// with them must be send '1' or property will be ignored (except _EDE_EVOKE_SPAWN)
|
||||
_ede_shutdown_all = XInternAtom(d, "_EDE_EVOKE_SHUTDOWN_ALL", False);
|
||||
@ -694,7 +721,10 @@ bool EvokeService::find_and_unregister_process(pid_t pid, EvokeProcess& pc) {
|
||||
int EvokeService::handle(const XEvent* ev) {
|
||||
logfile->printf("Got event %i\n", ev->type);
|
||||
|
||||
if(ev->type == MapNotify) {
|
||||
if(xsm && xsm->should_quit(ev)) {
|
||||
stop_xsettings_manager();
|
||||
return 1;
|
||||
} else if(ev->type == MapNotify) {
|
||||
if(top_win) {
|
||||
// for splash to keep it at top (working in old edewm)
|
||||
XRaiseWindow(fl_display, fl_xid(top_win));
|
||||
|
@ -14,10 +14,12 @@
|
||||
#define __EVOKESERVICE_H__
|
||||
|
||||
#include "Log.h"
|
||||
#include "Xsm.h"
|
||||
|
||||
#include <edelib/List.h>
|
||||
#include <edelib/String.h>
|
||||
#include <FL/x.h>
|
||||
|
||||
#include <FL/x.h>
|
||||
#include <pthread.h>
|
||||
|
||||
struct EvokeClient {
|
||||
@ -46,6 +48,7 @@ class EvokeService {
|
||||
private:
|
||||
bool is_running;
|
||||
Log* logfile;
|
||||
Xsm* xsm;
|
||||
char* pidfile;
|
||||
char* lockfile;
|
||||
|
||||
@ -73,6 +76,9 @@ class EvokeService {
|
||||
bool init_splash(const char* config, bool no_splash, bool dry_run);
|
||||
void init_autostart(bool safe);
|
||||
|
||||
void init_xsettings_manager(void);
|
||||
void stop_xsettings_manager(void);
|
||||
|
||||
int handle(const XEvent* ev);
|
||||
|
||||
Log* log(void) { return logfile; }
|
||||
|
@ -13,7 +13,7 @@ SubDir TOP evoke ;
|
||||
# use SIGHUP for now as default
|
||||
ObjectC++Flags evoke.cpp : -DUSE_SIGHUP ;
|
||||
|
||||
SOURCE = evoke.cpp EvokeService.cpp Spawn.cpp Splash.cpp Log.cpp Logout.cpp Crash.cpp Autostart.cpp ;
|
||||
SOURCE = evoke.cpp EvokeService.cpp Xsm.cpp Spawn.cpp Splash.cpp Log.cpp Logout.cpp Crash.cpp Autostart.cpp ;
|
||||
|
||||
LinkAgainst evoke : -lao -lvorbis -lvorbisfile -lmad ;
|
||||
|
||||
|
@ -26,7 +26,10 @@
|
||||
#define TIMEOUT_START 0.5 // timeout when splash is first time shown (also for first client)
|
||||
#define TIMEOUT_CONTINUE 2.0 // timeout between starting rest of the cliens
|
||||
|
||||
extern int xmessage_handler(int e);
|
||||
|
||||
int splash_xmessage_handler(int ev) {
|
||||
return EvokeService::instance()->handle(fl_xevent);
|
||||
}
|
||||
|
||||
/*
|
||||
* repeatedly call runner() untill all clients are
|
||||
@ -184,7 +187,7 @@ void Splash::run(void) {
|
||||
* and redirect them to EvokeService::handle().
|
||||
*/
|
||||
XSelectInput(fl_display, RootWindow(fl_display, fl_screen), SubstructureNotifyMask);
|
||||
Fl::add_handler(xmessage_handler);
|
||||
Fl::add_handler(splash_xmessage_handler);
|
||||
|
||||
// make sure MappingNotify keeps this window at the top
|
||||
EvokeService::instance()->register_top(this);
|
||||
|
154
evoke/Xsm.cpp
Normal file
154
evoke/Xsm.cpp
Normal 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;
|
||||
}
|
||||
|
53
evoke/Xsm.h
Normal file
53
evoke/Xsm.h
Normal file
@ -0,0 +1,53 @@
|
||||
/*
|
||||
* $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.
|
||||
*/
|
||||
|
||||
#ifndef __XSM_H__
|
||||
#define __XSM_H__
|
||||
|
||||
#include <X11/Xlib.h> // XEvent
|
||||
|
||||
/*
|
||||
* This is manager class for XSETTINGS protocol. XSETTINGS provides a mechanism
|
||||
* for applications to share simple configuration settings like background
|
||||
* colors no matter what toolkit is used. For now only gtk fully supports it
|
||||
* and support for ede apps is going to be added.
|
||||
*
|
||||
* The protocol (0.5 version) is described at:
|
||||
* http://standards.freedesktop.org/xsettings-spec/xsettings-spec-0.5.html
|
||||
*
|
||||
* This code is greatly based on xsettings referent implementation I found on
|
||||
* freedesktop.org cvs, since specs are very unclear about the details.
|
||||
* Author of referent implementation is Owen Taylor.
|
||||
*/
|
||||
|
||||
enum XsettingsType {
|
||||
XS_TYPE_INT = 0,
|
||||
XS_TYPE_COLOR,
|
||||
XS_TYPE_STRING
|
||||
};
|
||||
|
||||
struct XsmData;
|
||||
struct XsettingsSetting;
|
||||
|
||||
class Xsm {
|
||||
private:
|
||||
XsmData* data;
|
||||
|
||||
public:
|
||||
Xsm();
|
||||
~Xsm();
|
||||
bool is_running(void);
|
||||
bool init(void);
|
||||
bool should_quit(const XEvent* xev);
|
||||
};
|
||||
|
||||
#endif
|
@ -40,8 +40,12 @@ void quit_signal(int sig) {
|
||||
EvokeService::instance()->stop();
|
||||
}
|
||||
|
||||
int xmessage_handler(int e) {
|
||||
return EvokeService::instance()->handle(fl_xevent);
|
||||
void xmessage_handler(int, void*) {
|
||||
XEvent xev;
|
||||
while(XEventsQueued(fl_display, QueuedAfterReading)) {
|
||||
XNextEvent(fl_display, &xev);
|
||||
EvokeService::instance()->handle((const XEvent*)&xev);
|
||||
}
|
||||
}
|
||||
|
||||
const char* next_param(int curr, char** argv, int argc) {
|
||||
@ -165,6 +169,7 @@ int main(int argc, char** argv) {
|
||||
}
|
||||
|
||||
service->setup_atoms(fl_display);
|
||||
service->init_xsettings_manager();
|
||||
|
||||
signal(SIGINT, quit_signal);
|
||||
signal(SIGTERM, quit_signal);
|
||||
@ -193,8 +198,11 @@ int main(int argc, char** argv) {
|
||||
* and pass expecting ones to xmessage_handler(). Other (non-fltk) solution would
|
||||
* be to manually pool events via select() and that code could be very messy.
|
||||
* So stick with the simplicity :)
|
||||
*
|
||||
* Also note that '1' parameter means POLLIN, and for the details see Fl_x.cxx
|
||||
*/
|
||||
Fl::add_handler(xmessage_handler);
|
||||
Fl::add_fd(ConnectionNumber(fl_display), 1, xmessage_handler);
|
||||
|
||||
while(service->running())
|
||||
Fl::wait(FOREVER);
|
||||
|
||||
|
Reference in New Issue
Block a user