mirror of
https://github.com/edeproject/ede.git
synced 2023-08-10 21:13:03 +03:00
Call ede-keyboard-conf when clicked on applet.
Let ede-keyboard-conf uses setxkbmap for setting changes. ede-desktop foreign callback addopted for latest modification in edelib. ede-conf will display keyboard configuration.
This commit is contained in:
parent
dd6039098d
commit
cc9725582c
@ -1,26 +1,32 @@
|
|||||||
[EdeConf]
|
[EdeConf]
|
||||||
items = ede-desktop-conf,ede-screensaver-conf,ede-timedate, ede-bell-conf
|
items = ede-desktop-conf,ede-screensaver-conf,ede-timedate,ede-bell-conf,ede-keyboard-conf
|
||||||
|
|
||||||
[ede-desktop-conf]
|
[ede-desktop-conf]
|
||||||
name = Configure background and icons
|
name = Background and icons
|
||||||
tip = This item will configure desktop background and icons
|
tip = This item will configure desktop background and icons
|
||||||
exec = ede-desktop-conf
|
exec = ede-desktop-conf
|
||||||
icon = preferences-desktop-wallpaper
|
icon = preferences-desktop-wallpaper
|
||||||
|
|
||||||
[ede-screensaver-conf]
|
[ede-screensaver-conf]
|
||||||
name = Configure screensaver
|
name = Screensaver
|
||||||
tip = This item will setup screensaver settings
|
tip = This item will setup screensaver settings
|
||||||
exec = ede-screensaver-conf
|
exec = ede-screensaver-conf
|
||||||
icon = preferences-desktop-screensaver
|
icon = preferences-desktop-screensaver
|
||||||
|
|
||||||
[ede-timedate]
|
[ede-timedate]
|
||||||
name = Configure time and date
|
name = Time and date
|
||||||
tip = This item will configure system date and time
|
tip = This item will configure system date and time
|
||||||
exec = ede-timedate
|
exec = ede-timedate
|
||||||
icon = preferences-date-time
|
icon = preferences-date-time
|
||||||
|
|
||||||
[ede-bell-conf]
|
[ede-bell-conf]
|
||||||
name = Configure system bell
|
name = System bell
|
||||||
tip = This item will configure system bell
|
tip = This item will configure system bell
|
||||||
exec = ede-bell-conf
|
exec = ede-bell-conf
|
||||||
icon = audio-volume-zero
|
icon = audio-volume-zero
|
||||||
|
|
||||||
|
[ede-keyboard-conf]
|
||||||
|
name = Keyboard
|
||||||
|
tip = This item will configure keyboard preferences
|
||||||
|
exec = ede-keyboard-conf
|
||||||
|
icon = input-keyboard
|
||||||
|
@ -107,7 +107,7 @@ static void dir_watch_cb(const char* dir, const char* changed, int flags, void*
|
|||||||
Desktop::instance()->dir_watch(dir, changed, flags);
|
Desktop::instance()->dir_watch(dir, changed, flags);
|
||||||
}
|
}
|
||||||
|
|
||||||
static void settings_changed_cb(Fl_Window* win) {
|
static void settings_changed_cb(Fl_Window *win, void *data) {
|
||||||
Desktop::instance()->read_config();
|
Desktop::instance()->read_config();
|
||||||
Desktop::instance()->redraw();
|
Desktop::instance()->redraw();
|
||||||
}
|
}
|
||||||
@ -142,7 +142,7 @@ Desktop::Desktop() : DESKTOP_WINDOW(0, 0, 100, 100, "") {
|
|||||||
do_dirwatch = true;
|
do_dirwatch = true;
|
||||||
|
|
||||||
#ifdef USE_EDELIB_WINDOW
|
#ifdef USE_EDELIB_WINDOW
|
||||||
edelib::foreign_callback_add(this, settings_changed_cb, "ede-desktop");
|
edelib::foreign_callback_add(this, "ede-desktop", settings_changed_cb);
|
||||||
/* DESKTOP_WINDOW::single_bufer(true); */
|
/* DESKTOP_WINDOW::single_bufer(true); */
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
@ -33,12 +33,22 @@
|
|||||||
#include <edelib/Debug.h>
|
#include <edelib/Debug.h>
|
||||||
#include <edelib/String.h>
|
#include <edelib/String.h>
|
||||||
#include <edelib/Resource.h>
|
#include <edelib/Resource.h>
|
||||||
|
#include <edelib/File.h>
|
||||||
|
#include <edelib/Run.h>
|
||||||
|
#include <edelib/MessageBox.h>
|
||||||
|
#include <edelib/ForeignCallback.h>
|
||||||
|
|
||||||
#define CONFIG_NAME "ede-keyboard"
|
#define CONFIG_NAME "ede-keyboard"
|
||||||
|
#define PANEL_APPLET_ID "ede-keyboard"
|
||||||
|
#define DEFAULT_X_LAYOUT "us"
|
||||||
|
|
||||||
EDELIB_NS_USING_AS(Window, AppWindow)
|
EDELIB_NS_USING_AS(Window, AppWindow)
|
||||||
EDELIB_NS_USING(String)
|
EDELIB_NS_USING(String)
|
||||||
EDELIB_NS_USING(Resource)
|
EDELIB_NS_USING(Resource)
|
||||||
|
EDELIB_NS_USING(file_path)
|
||||||
|
EDELIB_NS_USING(run_sync)
|
||||||
|
EDELIB_NS_USING(alert)
|
||||||
|
EDELIB_NS_USING(foreign_callback_call)
|
||||||
|
|
||||||
static AppWindow *win;
|
static AppWindow *win;
|
||||||
static Fl_Hold_Browser *layout_browser;
|
static Fl_Hold_Browser *layout_browser;
|
||||||
@ -79,23 +89,20 @@ static void ok_cb(Fl_Widget*, void*) {
|
|||||||
dialog_canceled = false;
|
dialog_canceled = false;
|
||||||
}
|
}
|
||||||
|
|
||||||
static void fetch_current_layout(String &ret, String &rules_file_ret) {
|
static void fetch_current_layout(String ¤t) {
|
||||||
char *tmp = NULL;
|
char *rules_file;
|
||||||
XkbRF_VarDefsRec vd;
|
XkbRF_VarDefsRec vd;
|
||||||
|
|
||||||
E_ASSERT(fl_display != NULL);
|
|
||||||
|
|
||||||
/* get the layout straight from X since the layout can be changed during X session */
|
/* get the layout straight from X since the layout can be changed during X session */
|
||||||
if(!XkbRF_GetNamesProp(fl_display, &tmp, &vd) || !vd.layout)
|
if(!XkbRF_GetNamesProp(fl_display, &rules_file, &vd)) {
|
||||||
return;
|
/* use some values */
|
||||||
|
current = DEFAULT_X_LAYOUT;
|
||||||
|
} else {
|
||||||
|
current = vd.layout;
|
||||||
|
}
|
||||||
|
|
||||||
ret = vd.layout;
|
/* free everything */
|
||||||
|
XFree(rules_file);
|
||||||
/* remember rules filename too (on X.org is 'xorg')*/
|
|
||||||
rules_file_ret = tmp;
|
|
||||||
|
|
||||||
/* manually free each member */
|
|
||||||
XFree(tmp);
|
|
||||||
XFree(vd.layout);
|
XFree(vd.layout);
|
||||||
XFree(vd.model);
|
XFree(vd.model);
|
||||||
XFree(vd.options);
|
XFree(vd.options);
|
||||||
@ -164,31 +171,63 @@ static void save_config(const String &layout) {
|
|||||||
r.save(CONFIG_NAME);
|
r.save(CONFIG_NAME);
|
||||||
}
|
}
|
||||||
|
|
||||||
static void apply_layout_on_x(const String &layout, const String &rules_filename) {
|
static void apply_changes_on_x(const char *current) {
|
||||||
XkbRF_VarDefsRec vd;
|
|
||||||
vd.layout = (char*)layout.c_str();
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* rest fields must be zero-fied to prevent crash
|
* believe me, it is easier to call this command than to reimplmement a mess for
|
||||||
* FIXME: will this change other fields???
|
* uploading keyboard layout on X server!
|
||||||
*/
|
*/
|
||||||
vd.model = NULL;
|
String setxkbmap = file_path("setxkbmap");
|
||||||
vd.options = NULL;
|
if(setxkbmap.empty()) {
|
||||||
vd.variant = NULL;
|
alert(_("Unable to find 'setxkbmap' tool.\n\nThis tool is used as helper tool for "
|
||||||
|
"easier keyboard setup and is standard tool shipped with every X package. "
|
||||||
|
"Please install it first and run this program again."));
|
||||||
|
} else {
|
||||||
|
int ret = run_sync("%s %s", setxkbmap.c_str(), current);
|
||||||
|
/* do not show dialog since we can fail if config has bad entry when called from apply_chages_from_config() */
|
||||||
|
if(ret != 0)
|
||||||
|
E_WARNING(E_STRLOC ": 'setxkbmap %s' failed with %i\n", current, ret);
|
||||||
|
}
|
||||||
|
|
||||||
if(XkbRF_SetNamesProp(fl_display, (char*)rules_filename.c_str(), &vd) != True)
|
if(repeat_press->value())
|
||||||
E_WARNING(E_STRLOC ": Failed to update XKB rules\n");
|
XAutoRepeatOn(fl_display);
|
||||||
else
|
else
|
||||||
XSync(fl_display, False);
|
XAutoRepeatOff(fl_display);
|
||||||
|
|
||||||
|
/* force panel applet to re-read config file to see if flag should be displayed or not*/
|
||||||
|
foreign_callback_call(PANEL_APPLET_ID);
|
||||||
|
XFlush(fl_display);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void apply_chages_from_config(void) {
|
||||||
|
Resource r;
|
||||||
|
if(!r.load(CONFIG_NAME))
|
||||||
|
return;
|
||||||
|
|
||||||
|
char buf[32];
|
||||||
|
if(!r.get("Keyboard", "layout", buf, sizeof(buf)))
|
||||||
|
return;
|
||||||
|
|
||||||
|
/* TODO: this should be validated somehow */
|
||||||
|
apply_changes_on_x(buf);
|
||||||
}
|
}
|
||||||
|
|
||||||
int main(int argc, char **argv) {
|
int main(int argc, char **argv) {
|
||||||
String cl, rules_filename;
|
/* must be opened first */
|
||||||
|
|
||||||
/* needed for fetch_current_layout() and '--apply' */
|
|
||||||
fl_open_display();
|
fl_open_display();
|
||||||
|
|
||||||
|
/* only apply what was written in config */
|
||||||
|
if(argc > 1 && strcmp(argv[1], "--apply") == 0) {
|
||||||
|
apply_chages_from_config();
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
String cl;
|
||||||
dialog_canceled = false;
|
dialog_canceled = false;
|
||||||
|
|
||||||
|
/* get layout X holds */
|
||||||
|
fetch_current_layout(cl);
|
||||||
|
|
||||||
|
/* construct GUI */
|
||||||
win = new AppWindow(340, 320, _("Keyboard configuration tool"));
|
win = new AppWindow(340, 320, _("Keyboard configuration tool"));
|
||||||
win->begin();
|
win->begin();
|
||||||
Fl_Tabs *tabs = new Fl_Tabs(10, 10, 320, 265);
|
Fl_Tabs *tabs = new Fl_Tabs(10, 10, 320, 265);
|
||||||
@ -230,11 +269,8 @@ int main(int argc, char **argv) {
|
|||||||
cancel_button->callback(cancel_cb);
|
cancel_button->callback(cancel_cb);
|
||||||
win->end();
|
win->end();
|
||||||
|
|
||||||
/* read layouts */
|
/* read all XKB layouts */
|
||||||
XkbRF_RulesPtr xkb_rules;
|
XkbRF_RulesPtr xkb_rules = fetch_all_layouts(cl);
|
||||||
|
|
||||||
fetch_current_layout(cl, rules_filename);
|
|
||||||
xkb_rules = fetch_all_layouts(cl);
|
|
||||||
|
|
||||||
/* read configuration */
|
/* read configuration */
|
||||||
read_config();
|
read_config();
|
||||||
@ -249,7 +285,7 @@ int main(int argc, char **argv) {
|
|||||||
char *n = xkb_rules->layouts.desc[i - 1].name;
|
char *n = xkb_rules->layouts.desc[i - 1].name;
|
||||||
|
|
||||||
save_config(n);
|
save_config(n);
|
||||||
apply_layout_on_x(n, rules_filename);
|
apply_changes_on_x(n);
|
||||||
}
|
}
|
||||||
|
|
||||||
if(xkb_rules)
|
if(xkb_rules)
|
||||||
|
@ -16,20 +16,34 @@
|
|||||||
#include <edelib/List.h>
|
#include <edelib/List.h>
|
||||||
#include <edelib/Directory.h>
|
#include <edelib/Directory.h>
|
||||||
#include <edelib/Nls.h>
|
#include <edelib/Nls.h>
|
||||||
|
#include <edelib/Run.h>
|
||||||
|
#include <edelib/ForeignCallback.h>
|
||||||
|
|
||||||
|
/* they should match names in ede-keyboard-conf */
|
||||||
|
#define PANEL_APPLET_ID "ede-keyboard"
|
||||||
|
#define CONFIG_NAME "ede-keyboard"
|
||||||
|
|
||||||
EDELIB_NS_USING(Resource)
|
EDELIB_NS_USING(Resource)
|
||||||
EDELIB_NS_USING(String)
|
EDELIB_NS_USING(String)
|
||||||
EDELIB_NS_USING(list)
|
EDELIB_NS_USING(list)
|
||||||
|
EDELIB_NS_USING(run_async)
|
||||||
|
EDELIB_NS_USING(foreign_callback_add)
|
||||||
|
EDELIB_NS_USING(foreign_callback_remove)
|
||||||
EDELIB_NS_USING(RES_SYS_ONLY)
|
EDELIB_NS_USING(RES_SYS_ONLY)
|
||||||
|
|
||||||
static Atom _XA_XKB_RF_NAMES_PROP_ATOM = 0;
|
static Atom _XA_XKB_RF_NAMES_PROP_ATOM = 0;
|
||||||
|
|
||||||
class KeyLayout : public Fl_Button {
|
class KeyLayout : public Fl_Button {
|
||||||
private:
|
private:
|
||||||
String path, curr_layout;
|
bool should_show_flag;
|
||||||
|
String path, curr_layout;
|
||||||
|
Fl_Image *img;
|
||||||
|
|
||||||
public:
|
public:
|
||||||
KeyLayout();
|
KeyLayout();
|
||||||
void do_key_layout(void);
|
~KeyLayout();
|
||||||
|
void update_flag(bool read_config);
|
||||||
|
void do_key_layout();
|
||||||
int handle(int e);
|
int handle(int e);
|
||||||
};
|
};
|
||||||
|
|
||||||
@ -47,29 +61,53 @@ static void xkbrf_names_prop_free(XkbRF_VarDefsRec &vd, char *tmp) {
|
|||||||
XFree(vd.variant);
|
XFree(vd.variant);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* any layout changes on X will be reported here, executed either via ede-keyboard-conf or
|
||||||
|
* another tool, so there are no needs to read layout from configuration file
|
||||||
|
*/
|
||||||
static int xkb_events(int e) {
|
static int xkb_events(int e) {
|
||||||
if(fl_xevent->xproperty.atom == _XA_XKB_RF_NAMES_PROP_ATOM) {
|
if(fl_xevent->xproperty.atom == _XA_XKB_RF_NAMES_PROP_ATOM) {
|
||||||
/* TODO: lock this */
|
/* TODO: lock this */
|
||||||
KeyLayoutListIt it = keylayout_objects.begin(), it_end = keylayout_objects.end();
|
KeyLayoutListIt it = keylayout_objects.begin(), it_end = keylayout_objects.end();
|
||||||
|
|
||||||
for(; it != it_end; ++it)
|
for(; it != it_end; ++it) {
|
||||||
(*it)->do_key_layout();
|
(*it)->do_key_layout();
|
||||||
|
(*it)->update_flag(false);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static void click_cb(Fl_Widget*, void*) {
|
||||||
|
run_async("ede-keyboard-conf");
|
||||||
|
}
|
||||||
|
|
||||||
|
static void update_flag_cb(Fl_Window*, void *data) {
|
||||||
|
KeyLayout *k = (KeyLayout*)data;
|
||||||
|
k->update_flag(true);
|
||||||
|
k->redraw();
|
||||||
|
}
|
||||||
|
|
||||||
KeyLayout::KeyLayout() : Fl_Button(0, 0, 30, 25) {
|
KeyLayout::KeyLayout() : Fl_Button(0, 0, 30, 25) {
|
||||||
|
should_show_flag = true;
|
||||||
|
curr_layout = "us"; /* default layout */
|
||||||
|
img = NULL;
|
||||||
|
|
||||||
box(FL_FLAT_BOX);
|
box(FL_FLAT_BOX);
|
||||||
labelfont(FL_HELVETICA_BOLD);
|
labelfont(FL_HELVETICA_BOLD);
|
||||||
labelsize(10);
|
labelsize(10);
|
||||||
label("??");
|
label("??");
|
||||||
|
align(FL_ALIGN_CLIP);
|
||||||
|
|
||||||
tooltip(_("Current keyboard layout"));
|
tooltip(_("Current keyboard layout"));
|
||||||
|
callback(click_cb);
|
||||||
|
foreign_callback_add(window(), PANEL_APPLET_ID, update_flag_cb, this);
|
||||||
|
|
||||||
path = Resource::find_data("icons/kbflags/21x14", RES_SYS_ONLY, NULL);
|
path = Resource::find_data("icons/kbflags/21x14", RES_SYS_ONLY, NULL);
|
||||||
|
|
||||||
do_key_layout();
|
do_key_layout();
|
||||||
|
update_flag(true);
|
||||||
|
|
||||||
/* TODO: lock this */
|
/* TODO: lock this */
|
||||||
keylayout_objects.push_back(this);
|
keylayout_objects.push_back(this);
|
||||||
@ -81,6 +119,42 @@ KeyLayout::KeyLayout() : Fl_Button(0, 0, 30, 25) {
|
|||||||
Fl::add_handler(xkb_events);
|
Fl::add_handler(xkb_events);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
KeyLayout::~KeyLayout() {
|
||||||
|
foreign_callback_remove(update_flag_cb);
|
||||||
|
}
|
||||||
|
|
||||||
|
void KeyLayout::update_flag(bool read_config) {
|
||||||
|
if(read_config) {
|
||||||
|
Resource r;
|
||||||
|
|
||||||
|
if(r.load(CONFIG_NAME))
|
||||||
|
r.get("Keyboard", "show_country_flag", should_show_flag, true);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* remove previous image if we aren't going to show it */
|
||||||
|
if(!should_show_flag)
|
||||||
|
img = NULL;
|
||||||
|
|
||||||
|
if(should_show_flag && !path.empty()) {
|
||||||
|
/* construct image path that has the same name as layout */
|
||||||
|
String full_path = path;
|
||||||
|
|
||||||
|
full_path += E_DIR_SEPARATOR_STR;
|
||||||
|
full_path += curr_layout;
|
||||||
|
full_path += ".png";
|
||||||
|
|
||||||
|
img = Fl_Shared_Image::get(full_path.c_str());
|
||||||
|
}
|
||||||
|
|
||||||
|
image(img);
|
||||||
|
|
||||||
|
if(img)
|
||||||
|
label(NULL);
|
||||||
|
else
|
||||||
|
label(curr_layout.c_str());
|
||||||
|
redraw();
|
||||||
|
}
|
||||||
|
|
||||||
void KeyLayout::do_key_layout(void) {
|
void KeyLayout::do_key_layout(void) {
|
||||||
char *tmp = NULL;
|
char *tmp = NULL;
|
||||||
XkbRF_VarDefsRec vd;
|
XkbRF_VarDefsRec vd;
|
||||||
@ -92,31 +166,10 @@ void KeyLayout::do_key_layout(void) {
|
|||||||
if(!vd.layout || (curr_layout == vd.layout))
|
if(!vd.layout || (curr_layout == vd.layout))
|
||||||
return;
|
return;
|
||||||
|
|
||||||
|
/* just store it, so update_flag() can do the rest */
|
||||||
curr_layout = vd.layout;
|
curr_layout = vd.layout;
|
||||||
|
|
||||||
if(!path.empty()) {
|
|
||||||
/* construct image path that has the same name as layout */
|
|
||||||
String full_path = path;
|
|
||||||
|
|
||||||
full_path += E_DIR_SEPARATOR_STR;
|
|
||||||
full_path += curr_layout;
|
|
||||||
full_path += ".png";
|
|
||||||
|
|
||||||
img = Fl_Shared_Image::get(full_path.c_str());
|
|
||||||
}
|
|
||||||
|
|
||||||
if(img) {
|
|
||||||
image(img);
|
|
||||||
label(NULL);
|
|
||||||
} else {
|
|
||||||
image(NULL);
|
|
||||||
label(curr_layout.c_str());
|
|
||||||
}
|
|
||||||
|
|
||||||
xkbrf_names_prop_free(vd, tmp);
|
xkbrf_names_prop_free(vd, tmp);
|
||||||
}
|
}
|
||||||
|
|
||||||
redraw();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
int KeyLayout::handle(int e) {
|
int KeyLayout::handle(int e) {
|
||||||
|
Loading…
Reference in New Issue
Block a user