fluxbox/src/fluxbox.cc

1922 lines
61 KiB
C++
Raw Normal View History

// fluxbox.cc for Fluxbox Window Manager
2004-01-11 16:10:51 +00:00
// Copyright (c) 2001 - 2004 Henrik Kinnunen (fluxgen at users.sourceforge.net)
//
2001-12-11 20:47:02 +00:00
// blackbox.cc for blackbox - an X11 Window manager
2003-01-09 18:32:09 +00:00
// Copyright (c) 1997 - 2000 Brad Hughes (bhughes at tcac.net)
2001-12-11 20:47:02 +00:00
//
// Permission is hereby granted, free of charge, to any person obtaining a
// copy of this software and associated documentation files (the "Software"),
// to deal in the Software without restriction, including without limitation
// the rights to use, copy, modify, merge, publish, distribute, sublicense,
// and/or sell copies of the Software, and to permit persons to whom the
// Software is furnished to do so, subject to the following conditions:
//
// The above copyright notice and this permission notice shall be included in
// all copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
2003-01-09 18:32:09 +00:00
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
2001-12-11 20:47:02 +00:00
// THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
// DEALINGS IN THE SOFTWARE.
2004-11-19 11:37:27 +00:00
// $Id$
2002-08-13 21:19:00 +00:00
#include "fluxbox.hh"
2001-12-11 20:47:02 +00:00
#include "Screen.hh"
#include "Window.hh"
#include "Workspace.hh"
#include "AtomHandler.hh"
2003-02-17 12:31:17 +00:00
#include "FbCommands.hh"
2003-04-14 15:28:52 +00:00
#include "WinClient.hh"
2003-04-15 12:22:52 +00:00
#include "Keys.hh"
#include "FbAtoms.hh"
2003-06-30 20:37:57 +00:00
#include "defaults.hh"
2003-05-12 04:23:31 +00:00
2004-06-07 11:46:05 +00:00
#include "FbTk/I18n.hh"
#include "FbTk/Image.hh"
#include "FbTk/FileUtil.hh"
#include "FbTk/KeyUtil.hh"
2003-12-19 00:35:08 +00:00
#include "FbTk/ImageControl.hh"
#include "FbTk/EventManager.hh"
#include "FbTk/StringUtil.hh"
#include "FbTk/Resource.hh"
2004-01-13 12:55:25 +00:00
#include "FbTk/SimpleCommand.hh"
2003-12-19 00:35:08 +00:00
#include "FbTk/XrmDatabaseHelper.hh"
2004-01-11 13:10:39 +00:00
#include "FbTk/Command.hh"
#include "FbTk/RefCount.hh"
#include "FbTk/SimpleCommand.hh"
2004-02-27 12:32:54 +00:00
#include "FbTk/CompareEqual.hh"
#include "FbTk/Transparent.hh"
2002-08-13 21:19:00 +00:00
//Use GNU extensions
#ifndef _GNU_SOURCE
#define _GNU_SOURCE
#endif // _GNU_SOURCE
2003-01-09 18:32:09 +00:00
#ifdef HAVE_CONFIG_H
2003-05-07 23:17:38 +00:00
#include "config.h"
2002-08-13 21:19:00 +00:00
#endif // HAVE_CONFIG_H
#ifdef SLIT
#include "Slit.hh"
#endif // SLIT
#ifdef USE_GNOME
#include "Gnome.hh"
#endif // USE_GNOME
#ifdef USE_NEWWMSPEC
#include "Ewmh.hh"
#endif // USE_NEWWMSPEC
#ifdef REMEMBER
#include "Remember.hh"
#endif // REMEMBER
2003-06-25 13:07:34 +00:00
#ifdef USE_TOOLBAR
#include "Toolbar.hh"
2003-12-03 00:33:30 +00:00
#else
class Toolbar { };
2003-06-25 13:07:34 +00:00
#endif // USE_TOOLBAR
// X headers
2002-01-06 11:07:42 +00:00
#include <X11/Xlib.h>
#include <X11/Xutil.h>
#include <X11/Xresource.h>
#include <X11/Xatom.h>
#include <X11/keysym.h>
2003-05-12 04:23:31 +00:00
// X extensions
2002-08-02 13:00:23 +00:00
#ifdef SHAPE
2002-01-06 11:07:42 +00:00
#include <X11/extensions/shape.h>
#endif // SHAPE
2003-05-12 04:23:31 +00:00
#ifdef HAVE_RANDR
#include <X11/extensions/Xrandr.h>
#endif // HAVE_RANDR
// system headers
2002-01-06 11:07:42 +00:00
2004-08-31 15:26:40 +00:00
#ifdef HAVE_CSTDIO
#include <cstdio>
#else
#include <stdio.h>
#endif
#ifdef HAVE_CSTDLIB
#include <cstdlib>
#else
#include <stdlib.h>
#endif
#ifdef HAVE_CSTRING
#include <cstring>
#else
#include <string.h>
#endif
2001-12-11 20:47:02 +00:00
2002-08-02 13:00:23 +00:00
#ifdef HAVE_UNISTD_H
#include <sys/types.h>
#include <unistd.h>
2001-12-11 20:47:02 +00:00
#endif // HAVE_UNISTD_H
2002-08-02 13:00:23 +00:00
#ifdef HAVE_SYS_PARAM_H
#include <sys/param.h>
2001-12-11 20:47:02 +00:00
#endif // HAVE_SYS_PARAM_H
2002-08-02 13:00:23 +00:00
#ifdef HAVE_SYS_SELECT_H
#include <sys/select.h>
2001-12-11 20:47:02 +00:00
#endif // HAVE_SYS_SELECT_H
2003-05-11 22:19:17 +00:00
#ifdef HAVE_SYS_STAT_H
#include <sys/types.h>
#include <sys/stat.h>
2001-12-11 20:47:02 +00:00
#endif // HAVE_SYS_STAT_H
2003-05-11 22:19:17 +00:00
#ifdef TIME_WITH_SYS_TIME
#include <sys/time.h>
#include <time.h>
2001-12-11 20:47:02 +00:00
#else // !TIME_WITH_SYS_TIME
2003-05-11 22:19:17 +00:00
#ifdef HAVE_SYS_TIME_H
#include <sys/time.h>
#else // !HAVE_SYS_TIME_H
#include <time.h>
#endif // HAVE_SYS_TIME_H
2001-12-11 20:47:02 +00:00
#endif // TIME_WITH_SYS_TIME
#include <sys/wait.h>
2001-12-11 20:47:02 +00:00
#include <iostream>
#include <string>
2002-01-09 15:08:22 +00:00
#include <memory>
2002-07-14 01:00:23 +00:00
#include <algorithm>
#include <typeinfo>
2002-01-20 02:19:16 +00:00
using namespace std;
using namespace FbTk;
2001-12-11 20:47:02 +00:00
2003-08-12 21:00:54 +00:00
namespace {
Window last_bad_window = None;
int handleXErrors(Display *d, XErrorEvent *e) {
if (e->error_code == BadWindow)
last_bad_window = e->resourceid;
#ifdef DEBUG
else {
// ignore bad window ones, they happen a lot
// when windows close themselves
char errtxt[128];
XGetErrorText(d, e->error_code, errtxt, 128);
cerr<<"Fluxbox: X Error: "<<errtxt<<"("<<(int)e->error_code<<") opcodes "<<
(int)e->request_code<<"/"<<(int)e->minor_code<<" resource 0x"<<hex<<(int)e->resourceid<<dec<<endl;
}
#endif // !DEBUG
return False;
}
} // end anonymous
2001-12-11 20:47:02 +00:00
//static singleton var
2003-04-25 16:00:03 +00:00
Fluxbox *Fluxbox::s_singleton=0;
2001-12-11 20:47:02 +00:00
2002-03-01 15:28:56 +00:00
//default values for titlebar left and right
//don't forget to change last value in m_rc_titlebar_* if you add more to these
2003-04-25 16:00:03 +00:00
Fluxbox::Titlebar Fluxbox::s_titlebar_left[] = {STICK};
Fluxbox::Titlebar Fluxbox::s_titlebar_right[] = {MINIMIZE, MAXIMIZE, CLOSE};
2001-12-11 20:47:02 +00:00
2003-04-25 16:00:03 +00:00
Fluxbox::Fluxbox(int argc, char **argv, const char *dpy_name, const char *rcfilename)
: FbTk::App(dpy_name),
2003-04-15 12:22:52 +00:00
m_fbatoms(new FbAtoms()),
m_resourcemanager(rcfilename, true),
// TODO: shouldn't need a separate one for screen
m_screen_rm(m_resourcemanager),
2002-12-01 13:42:15 +00:00
m_rc_tabs(m_resourcemanager, true, "session.tabs", "Session.Tabs"),
m_rc_tabs_padding(m_resourcemanager, 0, "session.tabPadding", "Session.TabPadding"),
m_rc_focused_tab_min_width(m_resourcemanager, 0, "session.focusTabMinWidth",
"Session.FocusTabMinWidth"),
m_rc_ignoreborder(m_resourcemanager, false, "session.ignoreBorder", "Session.IgnoreBorder"),
m_rc_pseudotrans(m_resourcemanager, false, "session.forcePseudoTransparency", "Session.forcePseudoTransparency"),
m_rc_colors_per_channel(m_resourcemanager, 4,
2003-04-25 16:00:03 +00:00
"session.colorsPerChannel", "Session.ColorsPerChannel"),
m_rc_numlayers(m_resourcemanager, 13, "session.numLayers", "Session.NumLayers"),
2003-12-19 00:35:08 +00:00
m_rc_double_click_interval(m_resourcemanager, 250, "session.doubleClickInterval", "Session.DoubleClickInterval"),
m_rc_update_delay_time(m_resourcemanager, 0, "session.updateDelayTime", "Session.UpdateDelayTime"),
2002-12-01 13:42:15 +00:00
m_rc_stylefile(m_resourcemanager, "", "session.styleFile", "Session.StyleFile"),
m_rc_menufile(m_resourcemanager, DEFAULTMENU, "session.menuFile", "Session.MenuFile"),
m_rc_keyfile(m_resourcemanager, DEFAULTKEYSFILE, "session.keyFile", "Session.KeyFile"),
m_rc_slitlistfile(m_resourcemanager, "", "session.slitlistFile", "Session.SlitlistFile"),
m_rc_groupfile(m_resourcemanager, "", "session.groupFile", "Session.GroupFile"),
m_rc_appsfile(m_resourcemanager, "~/.fluxbox/apps", "session.appsFile", "Session.AppsFile"),
2003-04-25 16:00:03 +00:00
m_rc_titlebar_left(m_resourcemanager,
TitlebarList(&s_titlebar_left[0], &s_titlebar_left[1]),
"session.titlebar.left", "Session.Titlebar.Left"),
m_rc_titlebar_right(m_resourcemanager,
TitlebarList(&s_titlebar_right[0], &s_titlebar_right[3]),
2003-04-25 16:00:03 +00:00
"session.titlebar.right", "Session.Titlebar.Right"),
2004-04-22 21:07:57 +00:00
m_rc_tabs_attach_area(m_resourcemanager, ATTACH_AREA_WINDOW, "session.tabsAttachArea", "Session.TabsAttachArea"),
2002-12-01 13:42:15 +00:00
m_rc_cache_life(m_resourcemanager, 5, "session.cacheLife", "Session.CacheLife"),
m_rc_cache_max(m_resourcemanager, 200, "session.cacheMax", "Session.CacheMax"),
2003-10-05 06:28:47 +00:00
m_rc_auto_raise_delay(m_resourcemanager, 250, "session.autoRaiseDelay", "Session.AutoRaiseDelay"),
2003-12-31 00:35:21 +00:00
m_rc_use_mod1(m_resourcemanager, true, "session.useMod1", "Session.UseMod1"),
2003-12-30 20:56:41 +00:00
m_focused_window(0), m_masked_window(0),
m_mousescreen(0),
m_keyscreen(0),
2003-04-25 16:00:03 +00:00
m_watching_screen(0), m_watch_keyrelease(0),
m_last_time(0),
2003-12-30 20:56:41 +00:00
m_masked(0),
2003-04-25 16:00:03 +00:00
m_rc_file(rcfilename ? rcfilename : ""),
m_argv(argv), m_argc(argc),
m_starting(true),
m_restarting(false),
m_shutdown(false),
2003-05-11 22:19:17 +00:00
m_server_grabs(0),
2003-05-12 04:23:31 +00:00
m_randr_event_type(0),
2003-05-11 22:19:17 +00:00
m_RC_PATH("fluxbox"),
2003-12-30 20:56:41 +00:00
m_RC_INIT_FILE("init") {
2004-06-07 11:46:05 +00:00
_FB_USES_NLS;
2003-05-13 11:43:44 +00:00
if (s_singleton != 0)
2004-06-07 11:46:05 +00:00
throw string(_FBTEXT(Fluxbox, FatalSingleton, "Fatal! There can only one instance of fluxbox class.", "Error displayed on weird error where an instance of the Fluxbox class already exists!"));
2003-05-13 11:43:44 +00:00
if (display() == 0) {
throw string(_FBTEXT(Fluxbox, NoDisplay,
2004-06-07 11:46:05 +00:00
"Can not connect to X server.\nMake sure you started X before you start Fluxbox.",
"Error message when no X display appears to exist"));
2002-12-01 13:42:15 +00:00
}
2004-08-18 16:30:33 +00:00
2004-09-08 16:50:42 +00:00
Display *disp = FbTk::App::instance()->display();
2003-07-27 13:53:34 +00:00
// For KDE dock applets
// KDE v1.x
2004-09-08 16:50:42 +00:00
m_kwm1_dockwindow = XInternAtom(disp,
2003-07-27 13:53:34 +00:00
"KWM_DOCKWINDOW", False);
// KDE v2.x
2004-09-08 16:50:42 +00:00
m_kwm2_dockwindow = XInternAtom(disp,
2003-07-27 13:53:34 +00:00
"_KDE_NET_WM_SYSTEM_TRAY_WINDOW_FOR", False);
// setup X error handler
XSetErrorHandler((XErrorHandler) handleXErrors);
2002-12-01 13:42:15 +00:00
//catch system signals
SignalHandler &sigh = SignalHandler::instance();
2003-05-13 11:43:44 +00:00
sigh.registerHandler(SIGSEGV, this);
sigh.registerHandler(SIGFPE, this);
sigh.registerHandler(SIGTERM, this);
sigh.registerHandler(SIGINT, this);
sigh.registerHandler(SIGCHLD, this);
sigh.registerHandler(SIGHUP, this);
sigh.registerHandler(SIGUSR1, this);
2003-05-13 11:43:44 +00:00
sigh.registerHandler(SIGUSR2, this);
//
// setup timer
// This timer is used to we can issue a safe reconfig command.
// Because when the command is executed we shouldn't do reconfig directly
// because it could affect ongoing menu stuff so we need to reconfig in
// the next event "round".
FbTk::RefCount<FbTk::Command> reconfig_cmd(new FbTk::SimpleCommand<Fluxbox>(*this, &Fluxbox::timed_reconfigure));
timeval to;
to.tv_sec = 0;
to.tv_usec = 1;
m_reconfig_timer.setTimeout(to);
m_reconfig_timer.setCommand(reconfig_cmd);
m_reconfig_timer.fireOnce(true);
//XSynchronize(disp, True);
2003-05-13 11:43:44 +00:00
2003-04-25 16:00:03 +00:00
s_singleton = this;
2003-05-14 14:37:06 +00:00
m_have_shape = false;
m_shape_eventbase = 0;
#ifdef SHAPE
int shape_err;
2003-05-14 14:37:06 +00:00
m_have_shape = XShapeQueryExtension(disp, &m_shape_eventbase, &shape_err);
#endif // SHAPE
2002-12-01 13:42:15 +00:00
2003-05-12 04:23:31 +00:00
#ifdef HAVE_RANDR
// get randr event type
2004-01-09 11:37:01 +00:00
int randr_error_base;
XRRQueryExtension(disp, &m_randr_event_type, &randr_error_base);
2003-05-12 04:23:31 +00:00
#endif // HAVE_RANDR
load_rc();
// setup theme manager to have our style file ready to be scanned
FbTk::ThemeManager::instance().load(getStyleFilename());
2003-04-25 16:00:03 +00:00
// setup atom handlers before we create any windows
#ifdef REMEMBER
addAtomHandler(new Remember(), "remember"); // for remembering window attribs
#endif // REMEMBER
#ifdef USE_NEWWMSPEC
addAtomHandler(new Ewmh(), "ewmh"); // for Extended window manager atom support
#endif // USE_NEWWMSPEC
#ifdef USE_GNOME
addAtomHandler(new Gnome(), "gnome"); // for gnome 1 atom support
#endif //USE_GNOME
2002-08-18 11:01:52 +00:00
2002-12-01 13:42:15 +00:00
grab();
2002-12-01 13:42:15 +00:00
setupConfigFiles();
2002-12-01 13:42:15 +00:00
if (! XSupportsLocale())
2004-06-07 11:46:05 +00:00
cerr<<_FBTEXT(Fluxbox, WarningLocale, "Warning: X server does not support locale", "XSupportsLocale returned false")<<endl;
2001-12-11 20:47:02 +00:00
2002-12-01 13:42:15 +00:00
if (XSetLocaleModifiers("") == 0)
2004-06-07 11:46:05 +00:00
cerr<<_FBTEXT(Fluxbox, WarningLocaleModifiers, "Warning: cannot set locale modifiers", "XSetLocaleModifiers returned false")<<endl;
2001-12-11 20:47:02 +00:00
#ifdef HAVE_GETPID
2003-04-25 16:00:03 +00:00
m_fluxbox_pid = XInternAtom(disp, "_BLACKBOX_PID", False);
#endif // HAVE_GETPID
2001-12-11 20:47:02 +00:00
// Allocate screens
for (int i = 0; i < ScreenCount(display()); i++) {
2002-12-01 13:42:15 +00:00
char scrname[128], altscrname[128];
sprintf(scrname, "session.screen%d", i);
sprintf(altscrname, "session.Screen%d", i);
2004-01-21 13:36:09 +00:00
BScreen *screen = new BScreen(m_screen_rm.lock(),
2003-05-12 04:28:05 +00:00
scrname, altscrname,
i, getNumberOfLayers());
2002-12-01 13:42:15 +00:00
if (! screen->isScreenManaged()) {
delete screen;
2002-12-01 13:42:15 +00:00
continue;
}
// add to our list
m_screen_list.push_back(screen);
// now we can create menus (which needs this screen to be in screen_list)
screen->initMenus();
#ifdef HAVE_GETPID
pid_t bpid = getpid();
screen->rootWindow().changeProperty(getFluxboxPidAtom(), XA_CARDINAL,
sizeof(pid_t) * 8, PropModeReplace,
(unsigned char *) &bpid, 1);
#endif // HAVE_GETPID
2003-05-12 04:28:05 +00:00
#ifdef HAVE_RANDR
// setup RANDR for this screens root window
// we need to determine if we should use old randr select input function or not
#ifdef X_RRScreenChangeSelectInput
// use old set randr event
XRRScreenChangeSelectInput(disp, screen->rootWindow().window(), True);
#else
2003-05-12 04:28:05 +00:00
XRRSelectInput(disp, screen->rootWindow().window(),
RRScreenChangeNotifyMask);
#endif // X_RRScreenChangeSelectInput
2003-05-12 04:28:05 +00:00
#endif // HAVE_RANDR
2003-06-25 13:07:34 +00:00
#ifdef USE_TOOLBAR
m_toolbars.push_back(new Toolbar(*screen,
*screen->layerManager().
getLayer(Fluxbox::instance()->getNormalLayer())));
2003-06-25 13:07:34 +00:00
#endif // USE_TOOLBAR
// must do this after toolbar is created
screen->initWindows();
2002-12-01 13:42:15 +00:00
// attach screen signals to this
screen->currentWorkspaceSig().attach(this);
screen->workspaceCountSig().attach(this);
screen->workspaceNamesSig().attach(this);
screen->workspaceAreaSig().attach(this);
2002-12-01 13:42:15 +00:00
screen->clientListSig().attach(this);
2002-12-01 13:42:15 +00:00
// initiate atomhandler for screen specific stuff
for (AtomHandlerContainerIt it= m_atomhandler.begin();
it != m_atomhandler.end();
it++) {
(*it).first->initForScreen(*screen);
2002-12-01 13:42:15 +00:00
}
2003-12-03 00:33:30 +00:00
2003-12-30 20:56:41 +00:00
revertFocus(*screen); // make sure focus style is correct
2004-04-19 22:48:19 +00:00
#ifdef SLIT
if (screen->slit())
screen->slit()->show();
#endif // SLIT
2004-07-14 23:39:29 +00:00
2003-12-03 00:33:30 +00:00
} // end init screens
2004-04-26 09:25:42 +00:00
XAllowEvents(disp, ReplayPointer, CurrentTime);
2003-12-03 00:33:30 +00:00
m_keyscreen = m_mousescreen = m_screen_list.front();
2002-12-01 13:42:15 +00:00
2004-01-21 13:36:09 +00:00
if (m_screen_list.empty()) {
throw string(_FBTEXT(Fluxbox, ErrorNoScreens,
2004-06-07 11:46:05 +00:00
"Couldn't find screens to manage.\nMake sure you don't have another window manager running.", "Error message when no unmanaged screens found - usually means another window manager is running"));
2002-12-01 13:42:15 +00:00
}
2001-12-11 20:47:02 +00:00
// setup theme manager to have our style file ready to be scanned
2004-02-20 09:29:07 +00:00
FbTk::ThemeManager::instance().load(FbTk::StringUtil::expandFilename(getStyleFilename()));
2003-04-25 16:00:03 +00:00
XSynchronize(disp, False);
//XSynchronize(disp, True);
2003-12-04 21:31:02 +00:00
sync(false);
2003-04-25 16:00:03 +00:00
m_reconfigure_wait = m_reread_menu_wait = false;
// Create keybindings handler and load keys file
2003-04-25 16:00:03 +00:00
m_key.reset(new Keys(StringUtil::expandFilename(*m_rc_keyfile).c_str()));
2001-12-11 20:47:02 +00:00
m_resourcemanager.unlock();
2002-12-01 13:42:15 +00:00
ungrab();
#ifdef DEBUG
if (m_resourcemanager.lockDepth() != 0)
cerr<<"--- resource manager lockdepth = "<<m_resourcemanager.lockDepth()<<endl;
#endif //DEBUG
m_starting = false;
//
2003-12-19 00:35:08 +00:00
// For dumping theme items
// FbTk::ThemeManager::instance().listItems();
//
// m_resourcemanager.dump();
2004-07-14 23:39:29 +00:00
#ifdef USE_TOOLBAR
// finally, show toolbar
Toolbars::iterator toolbar_it = m_toolbars.begin();
Toolbars::iterator toolbar_it_end = m_toolbars.end();
for (; toolbar_it != toolbar_it_end; ++toolbar_it)
(*toolbar_it)->updateVisibleState();
#endif // USE_TOOLBAR
2001-12-11 20:47:02 +00:00
}
Fluxbox::~Fluxbox() {
2003-12-03 00:33:30 +00:00
// destroy toolbars
while (!m_toolbars.empty()) {
delete m_toolbars.back();
m_toolbars.pop_back();
}
// destroy screens
while (!m_screen_list.empty()) {
delete m_screen_list.back();
m_screen_list.pop_back();
}
2003-12-03 00:33:30 +00:00
2002-12-01 13:42:15 +00:00
// destroy atomhandlers
for (AtomHandlerContainerIt it= m_atomhandler.begin();
it != m_atomhandler.end();
it++) {
delete (*it).first;
2002-12-01 13:42:15 +00:00
}
m_atomhandler.clear();
2003-12-03 00:33:30 +00:00
clearMenuFilenames();
2001-12-11 20:47:02 +00:00
}
void Fluxbox::eventLoop() {
2003-10-09 16:48:09 +00:00
Display *disp = display();
2003-05-10 14:43:45 +00:00
while (!m_shutdown) {
2003-10-09 16:48:09 +00:00
if (XPending(disp)) {
XEvent e;
2003-10-09 16:48:09 +00:00
XNextEvent(disp, &e);
if (last_bad_window != None && e.xany.window == last_bad_window &&
e.type != DestroyNotify) { // we must let the actual destroys through
#ifdef DEBUG
2003-05-13 11:43:44 +00:00
cerr<<"Fluxbox::eventLoop(): removing bad window from event queue"<<endl;
#endif // DEBUG
} else {
last_bad_window = None;
handleEvent(&e);
}
} else {
2003-10-09 16:48:09 +00:00
FbTk::Timer::updateTimers(ConnectionNumber(disp)); //handle all timers
}
}
}
bool Fluxbox::validateWindow(Window window) const {
XEvent event;
if (XCheckTypedWindowEvent(display(), window, DestroyNotify, &event)) {
XPutBackEvent(display(), &event);
return false;
}
return true;
}
void Fluxbox::grab() {
if (! m_server_grabs++)
XGrabServer(display());
}
void Fluxbox::ungrab() {
if (! --m_server_grabs)
XUngrabServer(display());
2004-07-14 23:39:29 +00:00
if (m_server_grabs < 0)
m_server_grabs = 0;
}
2003-04-14 15:28:52 +00:00
/**
setup the configutation files in
2003-04-14 15:28:52 +00:00
home directory
*/
void Fluxbox::setupConfigFiles() {
2003-04-25 16:00:03 +00:00
bool create_init = false, create_keys = false, create_menu = false;
2002-12-01 13:42:15 +00:00
2003-08-12 21:00:54 +00:00
string dirname = getenv("HOME") + string("/.") + string(m_RC_PATH) + "/";
2003-04-25 16:00:03 +00:00
string init_file, keys_file, menu_file, slitlist_file;
2003-05-11 22:19:17 +00:00
init_file = dirname + m_RC_INIT_FILE;
keys_file = dirname + "keys";
menu_file = dirname + "menu";
2002-12-01 13:42:15 +00:00
struct stat buf;
// is file/dir already there?
if (! stat(dirname.c_str(), &buf)) {
2002-12-01 13:42:15 +00:00
// check if anything with those name exists, if not create new
2003-04-25 16:00:03 +00:00
if (stat(init_file.c_str(), &buf))
create_init = true;
if (stat(keys_file.c_str(), &buf))
create_keys = true;
if (stat(menu_file.c_str(), &buf))
create_menu = true;
2002-12-01 13:42:15 +00:00
} else {
#ifdef DEBUG
2002-12-01 13:42:15 +00:00
cerr <<__FILE__<<"("<<__LINE__<<"): Creating dir: " << dirname.c_str() << endl;
#endif // DEBUG
2004-06-07 11:46:05 +00:00
_FB_USES_NLS;
2002-12-01 13:42:15 +00:00
// create directory with perm 700
if (mkdir(dirname.c_str(), 0700)) {
fprintf(stderr, _FBTEXT(Fluxbox, ErrorCreatingDirectory,
2004-06-07 11:46:05 +00:00
"Can't create %s directory", "Can't create a directory, one %s for directory name"), dirname.c_str());
cerr<<endl;
return;
2002-12-01 13:42:15 +00:00
}
2002-12-01 13:42:15 +00:00
//mark creation of files
2003-04-25 16:00:03 +00:00
create_init = create_keys = create_menu = true;
2002-12-01 13:42:15 +00:00
}
2003-08-12 21:00:54 +00:00
// copy key configuration
if (create_keys)
FbTk::FileUtil::copyFile(DEFAULTKEYSFILE, keys_file.c_str());
2002-12-01 13:42:15 +00:00
2003-08-12 21:00:54 +00:00
// copy menu configuration
if (create_menu)
FbTk::FileUtil::copyFile(DEFAULTMENU, menu_file.c_str());
2002-12-01 13:42:15 +00:00
2003-08-12 21:00:54 +00:00
// copy init file
if (create_init)
FbTk::FileUtil::copyFile(DEFAULT_INITFILE, init_file.c_str());
2002-12-01 13:42:15 +00:00
}
2001-12-11 20:47:02 +00:00
void Fluxbox::handleEvent(XEvent * const e) {
2004-06-07 11:46:05 +00:00
_FB_USES_NLS;
m_last_event = *e;
2001-12-11 20:47:02 +00:00
2003-03-22 05:13:08 +00:00
// it is possible (e.g. during moving) for a window
// to mask all events to go to it
2003-12-30 20:56:41 +00:00
if ((m_masked == e->xany.window) && m_masked_window) {
if (e->type == MotionNotify) {
m_last_time = e->xmotion.time;
m_masked_window->motionNotifyEvent(e->xmotion);
return;
2003-12-30 20:56:41 +00:00
} else if (e->type == ButtonRelease) {
e->xbutton.window = m_masked_window->fbWindow().window();
}
2002-12-01 13:42:15 +00:00
}
2003-12-21 22:42:31 +00:00
// update key/mouse screen and last time before we enter other eventhandlers
if (e->type == KeyPress ||
e->type == KeyRelease) {
m_keyscreen = searchScreen(e->xkey.root);
} else if (e->type == ButtonPress ||
e->type == ButtonRelease ||
e->type == MotionNotify ) {
2003-12-21 22:42:31 +00:00
if (e->type == MotionNotify)
m_last_time = e->xmotion.time;
else
m_last_time = e->xbutton.time;
m_mousescreen = searchScreen(e->xbutton.root);
} else if (e->type == EnterNotify ||
e->type == LeaveNotify) {
2003-12-21 22:42:31 +00:00
m_last_time = e->xcrossing.time;
m_mousescreen = searchScreen(e->xcrossing.root);
2003-12-21 22:42:31 +00:00
} else if (e->type == PropertyNotify)
m_last_time = e->xproperty.time;
// we need to check focus out for menus before
// we call FbTk eventhandler
// so we can get FbTk::Menu::focused() before it sets to 0
if (e->type == FocusOut &&
e->xfocus.mode != NotifyGrab &&
e->xfocus.detail != NotifyPointer &&
e->xfocus.detail != NotifyInferior &&
FbTk::Menu::focused() != 0 &&
FbTk::Menu::focused()->window() == e->xfocus.window) {
2004-01-16 11:38:30 +00:00
// find screen num
BScreen *screen = 0;
ScreenList::iterator it = m_screen_list.begin();
ScreenList::iterator it_end = m_screen_list.end();
for (; it != it_end; ++it) {
if ( (*it)->screenNumber() ==
2004-01-16 11:38:30 +00:00
FbTk::Menu::focused()->fbwindow().screenNumber()) {
screen = (*it);
break; // found the screen, no more search
}
}
2004-01-16 11:38:30 +00:00
if (screen != 0)
revertFocus(*screen);
}
2002-12-03 23:58:06 +00:00
// try FbTk::EventHandler first
FbTk::EventManager::instance()->handleEvent(*e);
2002-12-01 13:42:15 +00:00
switch (e->type) {
case ButtonRelease:
case ButtonPress:
handleButtonEvent(e->xbutton);
break;
2003-04-25 16:00:03 +00:00
case ConfigureRequest: {
if (!searchWindow(e->xconfigurerequest.window)) {
2003-04-25 16:00:03 +00:00
grab();
if (validateWindow(e->xconfigurerequest.window)) {
XWindowChanges xwc;
xwc.x = e->xconfigurerequest.x;
xwc.y = e->xconfigurerequest.y;
xwc.width = e->xconfigurerequest.width;
xwc.height = e->xconfigurerequest.height;
xwc.border_width = e->xconfigurerequest.border_width;
xwc.sibling = e->xconfigurerequest.above;
xwc.stack_mode = e->xconfigurerequest.detail;
XConfigureWindow(FbTk::App::instance()->display(),
e->xconfigurerequest.window,
e->xconfigurerequest.value_mask, &xwc);
2002-12-01 13:42:15 +00:00
}
2001-12-11 20:47:02 +00:00
2003-04-25 16:00:03 +00:00
ungrab();
} // else already handled in FluxboxWindow::handleEvent
2003-04-25 16:00:03 +00:00
}
2002-12-02 23:49:56 +00:00
break;
case MapRequest: {
2003-07-23 10:43:30 +00:00
#ifdef DEBUG
cerr<<"MapRequest for 0x"<<hex<<e->xmaprequest.window<<dec<<endl;
2002-08-04 15:00:50 +00:00
#endif // DEBUG
2002-12-02 23:49:56 +00:00
WinClient *winclient = searchWindow(e->xmaprequest.window);
FluxboxWindow *win = 0;
if (! winclient) {
2004-01-18 12:42:47 +00:00
BScreen *screen = 0;
int screen_num;
XWindowAttributes attr;
// find screen
if (XGetWindowAttributes(display(),
e->xmaprequest.window,
&attr) && attr.screen != 0) {
screen_num = XScreenNumberOfScreen(attr.screen);
2004-01-18 12:42:47 +00:00
// find screen
2004-02-27 12:32:54 +00:00
ScreenList::iterator screen_it = find_if(m_screen_list.begin(),
m_screen_list.end(),
FbTk::CompareEqual<BScreen>(&BScreen::screenNumber, screen_num));
if (screen_it != m_screen_list.end())
screen = *screen_it;
2004-01-18 12:42:47 +00:00
}
// try with parent if we failed to find screen num
if (screen == 0)
screen = searchScreen(e->xmaprequest.parent);
2004-01-18 12:42:47 +00:00
if (screen == 0) {
2004-06-07 11:46:05 +00:00
cerr<<"Fluxbox "<<_FBTEXT(Fluxbox, CantMapWindow, "Warning! Could not find screen to map window on!", "")<<endl;
2004-01-18 12:42:47 +00:00
} else
win = screen->createWindow(e->xmaprequest.window);
} else {
win = winclient->fbwindow();
}
2003-04-25 16:00:03 +00:00
// we don't handle MapRequest in FluxboxWindow::handleEvent
if (win)
2003-04-16 10:49:59 +00:00
win->mapRequestEvent(e->xmaprequest);
}
2002-12-02 23:49:56 +00:00
break;
2004-07-14 23:39:29 +00:00
case MapNotify:
2003-04-27 00:36:28 +00:00
// handled directly in FluxboxWindow::handleEvent
2004-07-14 23:39:29 +00:00
break;
2002-12-01 13:42:15 +00:00
case UnmapNotify:
handleUnmapNotify(e->xunmap);
break;
case MappingNotify:
// Update stored modifier mapping
#ifdef DEBUG
cerr<<__FILE__<<"("<<__FUNCTION__<<"): MappingNotify"<<endl;
#endif // DEBUG
2003-10-13 19:31:04 +00:00
FbTk::KeyUtil::instance().init(); // reinitialise the key utils
// reconfigure keys (if the mapping changes, they don't otherwise update
m_key->reconfigure(StringUtil::expandFilename(*m_rc_keyfile).c_str());
break;
2002-12-01 13:42:15 +00:00
case CreateNotify:
break;
2002-12-01 13:42:15 +00:00
case DestroyNotify: {
WinClient *winclient = searchWindow(e->xdestroywindow.window);
if (winclient != 0) {
FluxboxWindow *win = winclient->fbwindow();
if (win)
2003-04-14 15:28:52 +00:00
win->destroyNotifyEvent(e->xdestroywindow);
delete winclient;
if (win && win->numClients() == 0)
delete win;
}
2001-12-11 20:47:02 +00:00
2002-12-01 13:42:15 +00:00
}
2002-12-02 23:49:56 +00:00
break;
case MotionNotify:
m_last_time = e->xmotion.time;
2002-12-02 23:49:56 +00:00
break;
case PropertyNotify: {
2003-04-25 16:00:03 +00:00
m_last_time = e->xproperty.time;
WinClient *winclient = searchWindow(e->xproperty.window);
if (winclient == 0)
break;
// most of them are handled in FluxboxWindow::handleEvent
// but some special cases like ewmh propertys needs to be checked
for (AtomHandlerContainerIt it= m_atomhandler.begin();
it != m_atomhandler.end(); it++) {
if ( (*it).first->propertyNotify(*winclient, e->xproperty.atom))
break;
}
} break;
2002-12-01 13:42:15 +00:00
case EnterNotify: {
2004-07-14 23:39:29 +00:00
2003-04-25 16:00:03 +00:00
m_last_time = e->xcrossing.time;
2002-12-03 23:58:06 +00:00
BScreen *screen = 0;
2002-12-01 13:42:15 +00:00
if (e->xcrossing.mode == NotifyGrab)
break;
if ((e->xcrossing.window == e->xcrossing.root) &&
(screen = searchScreen(e->xcrossing.window))) {
2003-05-15 23:30:07 +00:00
screen->imageControl().installRootColormap();
2001-12-11 20:47:02 +00:00
}
2003-04-25 16:00:03 +00:00
} break;
2002-12-01 13:42:15 +00:00
case LeaveNotify:
2004-07-14 23:39:29 +00:00
2003-04-25 16:00:03 +00:00
m_last_time = e->xcrossing.time;
2002-12-02 23:49:56 +00:00
break;
2002-12-01 13:42:15 +00:00
case Expose:
2002-12-02 23:49:56 +00:00
break;
case KeyRelease:
2002-12-01 13:42:15 +00:00
case KeyPress:
handleKeyEvent(e->xkey);
break;
2002-12-01 13:42:15 +00:00
case ColormapNotify: {
BScreen *screen = searchScreen(e->xcolormap.window);
if (screen != 0) {
screen->setRootColormapInstalled((e->xcolormap.state ==
2003-04-25 16:00:03 +00:00
ColormapInstalled) ? true : false);
2002-12-01 13:42:15 +00:00
}
2003-04-25 16:00:03 +00:00
} break;
2002-12-01 13:42:15 +00:00
case FocusIn: {
2003-12-09 12:28:24 +00:00
2003-09-14 11:23:48 +00:00
// a grab is something of a pseudo-focus event, so we ignore
// them, here we ignore some window receiving it
if (e->xfocus.mode == NotifyGrab ||
2003-12-09 12:28:24 +00:00
e->xfocus.detail == NotifyPointer ||
e->xfocus.detail == NotifyInferior)
2002-12-01 13:42:15 +00:00
break;
WinClient *winclient = searchWindow(e->xfocus.window);
if (winclient && m_focused_window != winclient)
setFocusedWindow(winclient);
2003-12-09 12:28:24 +00:00
2002-12-01 13:42:15 +00:00
} break;
case FocusOut:{
2003-09-14 11:23:48 +00:00
// and here we ignore some window losing the special grab focus
2003-09-14 11:56:11 +00:00
if (e->xfocus.mode == NotifyGrab ||
2003-12-09 12:28:24 +00:00
e->xfocus.detail == NotifyPointer ||
e->xfocus.detail == NotifyInferior)
break;
2003-12-09 12:28:24 +00:00
WinClient *winclient = searchWindow(e->xfocus.window);
if (winclient == 0 && FbTk::Menu::focused() == 0) {
#ifdef DEBUG
cerr<<__FILE__<<"("<<__FUNCTION__<<") Focus out is not a FluxboxWindow !!"<<endl;
#endif // DEBUG
} else if (winclient && winclient == m_focused_window &&
(winclient->fbwindow() == 0
|| !winclient->fbwindow()->isMoving()))
// we don't unfocus a moving window
setFocusedWindow(0);
}
break;
2002-12-01 13:42:15 +00:00
case ClientMessage:
handleClientMessage(e->xclient);
break;
2002-12-01 13:42:15 +00:00
default: {
2003-05-12 04:23:31 +00:00
#ifdef HAVE_RANDR
if (e->type == m_randr_event_type) {
// update root window size in screen
BScreen *scr = searchScreen(e->xany.window);
if (scr != 0)
scr->updateSize();
2003-05-14 14:37:06 +00:00
}
2003-05-12 04:23:31 +00:00
#endif // HAVE_RANDR
2002-12-02 23:49:56 +00:00
}
2002-12-01 13:42:15 +00:00
}
}
2001-12-11 20:47:02 +00:00
void Fluxbox::handleButtonEvent(XButtonEvent &be) {
2002-12-01 13:42:15 +00:00
switch (be.type) {
2003-04-25 16:00:03 +00:00
case ButtonPress: {
m_last_time = be.time;
2003-04-14 15:28:52 +00:00
2003-04-25 16:00:03 +00:00
BScreen *screen = searchScreen(be.window);
if (screen == 0)
break; // end case
2004-01-11 16:10:51 +00:00
screen->hideMenus();
2003-12-03 00:49:20 +00:00
// strip num/caps/scroll-lock and
2003-12-31 00:35:21 +00:00
// see if we're using any other modifier,
// if we're we shouldn't show the root menu
// this could happen if we're resizing aterm for instance
if (FbTk::KeyUtil::instance().cleanMods(be.state) != 0)
return;
2003-04-25 16:00:03 +00:00
if (be.button == 1) {
if (! screen->isRootColormapInstalled())
2003-05-15 23:30:07 +00:00
screen->imageControl().installRootColormap();
// hide menus
2003-12-19 00:35:08 +00:00
if (screen->getRootmenu().isVisible())
screen->getRootmenu().hide();
if (screen->getWorkspacemenu().isVisible())
screen->getWorkspacemenu().hide();
2003-04-25 16:00:03 +00:00
} else if (be.button == 2) {
FbCommands::ShowWorkspaceMenuCmd cmd;
cmd.execute();
} else if (be.button == 3) {
FbCommands::ShowRootMenuCmd cmd;
cmd.execute();
2003-04-25 16:00:03 +00:00
} else if (screen->isDesktopWheeling() && be.button == 4) {
screen->nextWorkspace(1);
} else if (screen->isDesktopWheeling() && be.button == 5) {
screen->prevWorkspace(1);
2002-12-01 13:42:15 +00:00
}
2003-04-25 16:00:03 +00:00
} break;
2002-12-01 13:42:15 +00:00
case ButtonRelease:
m_last_time = be.time;
break;
2002-12-01 13:42:15 +00:00
default:
2003-04-25 16:00:03 +00:00
break;
2002-12-01 13:42:15 +00:00
}
}
2001-12-11 20:47:02 +00:00
2002-02-17 18:43:30 +00:00
void Fluxbox::handleUnmapNotify(XUnmapEvent &ue) {
2002-12-01 13:42:15 +00:00
BScreen *screen = searchScreen(ue.event);
if (ue.event != ue.window && (!screen || !ue.send_event)) {
2002-12-01 13:42:15 +00:00
return;
}
WinClient *winclient = 0;
if ((winclient = searchWindow(ue.window)) != 0) {
2003-04-14 15:28:52 +00:00
if (winclient != 0) {
FluxboxWindow *win = winclient->fbwindow();
if (!win) {
delete winclient;
return;
}
// this should delete client and adjust m_focused_window if necessary
win->unmapNotifyEvent(ue);
2002-12-01 13:42:15 +00:00
winclient = 0; // it's invalid now when win destroyed the client
2003-04-14 15:28:52 +00:00
// finally destroy window if empty
2003-04-14 15:28:52 +00:00
if (win->numClients() == 0) {
delete win;
win = 0;
}
}
// according to http://tronche.com/gui/x/icccm/sec-4.html#s-4.1.4
// a XWithdrawWindow is
// 1) unmapping the window (which leads to the upper branch
// 2) sends an synthetic unampevent (which is handled below)
} else if (screen && ue.send_event) {
XDeleteProperty(display(), ue.window, FbAtoms::instance()->getWMStateAtom());
XUngrabButton(display(), AnyButton, AnyModifier, ue.window);
2002-12-01 13:42:15 +00:00
}
2002-02-17 18:43:30 +00:00
}
2003-04-14 15:28:52 +00:00
/**
* Handles XClientMessageEvent
*/
void Fluxbox::handleClientMessage(XClientMessageEvent &ce) {
2004-01-21 15:30:27 +00:00
#ifdef DEBUG
2004-01-11 16:10:51 +00:00
char * atom = 0;
if (ce.message_type)
atom = XGetAtomName(FbTk::App::instance()->display(), ce.message_type);
2002-12-01 13:42:15 +00:00
cerr<<__FILE__<<"("<<__LINE__<<"): ClientMessage. data.l[0]=0x"<<hex<<ce.data.l[0]<<
" message_type=0x"<<ce.message_type<<dec<<" = \""<<atom<<"\""<<endl;
if (ce.message_type && atom) XFree((char *) atom);
2004-01-21 15:30:27 +00:00
#endif // DEBUG
2001-12-11 20:47:02 +00:00
2002-12-01 13:42:15 +00:00
if (ce.format != 32)
return;
2003-04-15 12:22:52 +00:00
if (ce.message_type == m_fbatoms->getWMChangeStateAtom()) {
WinClient *winclient = searchWindow(ce.window);
if (! winclient || !winclient->fbwindow() || ! winclient->validateClient())
2002-12-01 13:42:15 +00:00
return;
if (ce.data.l[0] == IconicState)
winclient->fbwindow()->iconify();
2002-12-01 13:42:15 +00:00
if (ce.data.l[0] == NormalState)
winclient->fbwindow()->deiconify();
2003-04-15 12:22:52 +00:00
} else if (ce.message_type == m_fbatoms->getFluxboxChangeWorkspaceAtom()) {
2002-12-01 13:42:15 +00:00
BScreen *screen = searchScreen(ce.window);
if (screen && ce.data.l[0] >= 0 &&
ce.data.l[0] < (signed)screen->getCount())
screen->changeWorkspaceID(ce.data.l[0]);
2003-04-15 12:22:52 +00:00
} else if (ce.message_type == m_fbatoms->getFluxboxChangeWindowFocusAtom()) {
WinClient *winclient = searchWindow(ce.window);
if (winclient) {
FluxboxWindow *win = winclient->fbwindow();
if (win && win->isVisible())
win->setCurrentClient(*winclient, true);
}
2003-04-15 12:22:52 +00:00
} else if (ce.message_type == m_fbatoms->getFluxboxCycleWindowFocusAtom()) {
2002-12-01 13:42:15 +00:00
BScreen *screen = searchScreen(ce.window);
if (screen) {
if (! ce.data.l[0])
screen->prevFocus();
else
screen->nextFocus();
}
2003-04-15 12:22:52 +00:00
} else if (ce.message_type == m_fbatoms->getFluxboxChangeAttributesAtom()) {
WinClient *winclient = searchWindow(ce.window);
FluxboxWindow *win = 0;
if (winclient && (win = winclient->fbwindow()) && winclient->validateClient()) {
FluxboxWindow::BlackboxHints net;
2002-12-01 13:42:15 +00:00
net.flags = ce.data.l[0];
net.attrib = ce.data.l[1];
net.workspace = ce.data.l[2];
net.stack = ce.data.l[3];
net.decoration = static_cast<int>(ce.data.l[4]);
win->changeBlackboxHints(net);
2002-12-01 13:42:15 +00:00
}
} else {
WinClient *winclient = searchWindow(ce.window);
2002-12-01 13:42:15 +00:00
BScreen *screen = searchScreen(ce.window);
// note: we dont need screen nor winclient to be non-null,
2003-08-15 13:57:18 +00:00
// it's up to the atomhandler to check that
for (AtomHandlerContainerIt it= m_atomhandler.begin();
it != m_atomhandler.end(); it++) {
(*it).first->checkClientMessage(ce, screen, winclient);
2002-12-01 13:42:15 +00:00
}
2003-08-15 13:57:18 +00:00
2002-12-01 13:42:15 +00:00
}
2001-12-11 20:47:02 +00:00
}
2003-04-14 15:28:52 +00:00
/**
Handles KeyRelease and KeyPress events
*/
void Fluxbox::handleKeyEvent(XKeyEvent &ke) {
if (keyScreen() == 0 || mouseScreen() == 0)
return;
2003-04-25 16:00:03 +00:00
switch (ke.type) {
case KeyPress:
m_key->doAction(ke);
break;
2003-04-25 16:00:03 +00:00
case KeyRelease: {
// we ignore most key releases unless we need to use
// a release to stop something (e.g. window cycling).
// we notify if _all_ of the watched modifiers are released
if (m_watching_screen && m_watch_keyrelease) {
// mask the mod of the released key out
// won't mask anything if it isn't a mod
2003-12-30 20:56:41 +00:00
ke.state &= ~FbTk::KeyUtil::instance().keycodeToModmask(ke.keycode);
2003-04-25 16:00:03 +00:00
if ((m_watch_keyrelease & ke.state) == 0) {
2003-04-25 16:00:03 +00:00
m_watching_screen->notifyReleasedKeys(ke);
XUngrabKeyboard(FbTk::App::instance()->display(), CurrentTime);
2003-04-25 16:00:03 +00:00
// once they are released, we drop the watch
m_watching_screen = 0;
m_watch_keyrelease = 0;
}
2003-04-25 16:00:03 +00:00
}
2003-04-25 16:00:03 +00:00
break;
}
2002-12-01 13:42:15 +00:00
default:
2003-04-14 15:28:52 +00:00
break;
2002-12-01 13:42:15 +00:00
}
2001-12-11 20:47:02 +00:00
}
2003-04-14 15:28:52 +00:00
/// handle system signals
2002-11-27 22:00:19 +00:00
void Fluxbox::handleSignal(int signum) {
2004-06-07 11:46:05 +00:00
_FB_USES_NLS;
2002-12-01 13:42:15 +00:00
static int re_enter = 0;
switch (signum) {
case SIGCHLD: // we don't want the child process to kill us
waitpid(-1, 0, WNOHANG | WUNTRACED);
break;
case SIGHUP:
load_rc();
break;
case SIGUSR1:
reload_rc();
break;
case SIGUSR2:
rereadMenu();
break;
case SIGSEGV:
abort();
break;
case SIGFPE:
case SIGINT:
case SIGTERM:
shutdown();
break;
default:
fprintf(stderr,
2004-06-07 11:46:05 +00:00
_FBTEXT(BaseDisplay, SignalCaught, "%s: signal %d caught\n", "signal catch debug message. Include %s for command and %d for signal number"),
m_argv[0], signum);
2002-12-01 13:42:15 +00:00
if (! m_starting && ! re_enter) {
2002-12-01 13:42:15 +00:00
re_enter = 1;
fprintf(stderr,
2004-06-07 11:46:05 +00:00
_FBTEXT(BaseDisplay, ShuttingDown, "Shutting Down\n", "Quitting because of signal, end with newline"));
2002-12-01 13:42:15 +00:00
shutdown();
}
2002-12-01 13:42:15 +00:00
fprintf(stderr,
2004-06-07 11:46:05 +00:00
_FBTEXT(BaseDisplay, Aborting, "Aborting... dumping core\n", "Aboring and dumping core, end with newline"));
2002-12-01 13:42:15 +00:00
abort();
break;
}
}
void Fluxbox::update(FbTk::Subject *changedsub) {
2003-04-14 15:28:52 +00:00
//TODO: fix signaling, this does not look good
2003-03-03 21:51:13 +00:00
if (typeid(*changedsub) == typeid(FluxboxWindow::WinSubject)) {
2002-12-01 13:42:15 +00:00
FluxboxWindow::WinSubject *winsub = dynamic_cast<FluxboxWindow::WinSubject *>(changedsub);
FluxboxWindow &win = winsub->win();
if ((&(win.hintSig())) == changedsub) { // hint signal
for (AtomHandlerContainerIt it= m_atomhandler.begin();
it != m_atomhandler.end(); ++it) {
if ( (*it).first->update())
(*it).first->updateHints(win);
2002-12-01 13:42:15 +00:00
}
} else if ((&(win.stateSig())) == changedsub) { // state signal
for (AtomHandlerContainerIt it= m_atomhandler.begin();
it != m_atomhandler.end(); ++it) {
if ((*it).first->update())
(*it).first->updateState(win);
2002-12-01 13:42:15 +00:00
}
2003-04-14 15:28:52 +00:00
// if window changed to iconic state
// add to icon list
if (win.isIconic()) {
2003-05-15 11:17:29 +00:00
Workspace *space = win.screen().getWorkspace(win.workspaceNumber());
2003-04-14 15:28:52 +00:00
if (space != 0)
2004-03-21 09:00:25 +00:00
space->removeWindow(&win, true);
2003-05-11 13:36:12 +00:00
win.screen().addIcon(&win);
2003-04-14 15:28:52 +00:00
}
if (win.isStuck()) {
// if we're sticky then reassociate window
// to all workspaces
2003-05-11 13:36:12 +00:00
BScreen &scr = win.screen();
2003-05-15 12:00:46 +00:00
if (scr.currentWorkspaceID() != win.workspaceNumber()) {
scr.reassociateWindow(&win,
2003-05-15 12:00:46 +00:00
scr.currentWorkspaceID(),
2003-04-14 15:28:52 +00:00
true);
}
}
} else if ((&(win.layerSig())) == changedsub) { // layer signal
2003-04-14 15:28:52 +00:00
for (AtomHandlerContainerIt it= m_atomhandler.begin();
it != m_atomhandler.end(); ++it) {
if ((*it).first->update())
(*it).first->updateLayer(win);
}
2003-03-03 21:51:13 +00:00
} else if ((&(win.dieSig())) == changedsub) { // window death signal
for (AtomHandlerContainerIt it= m_atomhandler.begin();
it != m_atomhandler.end(); ++it) {
if ((*it).first->update())
(*it).first->updateFrameClose(win);
2003-03-03 21:51:13 +00:00
}
// make sure each workspace get this
2003-05-11 13:36:12 +00:00
BScreen &scr = win.screen();
scr.removeWindow(&win);
if (m_focused_window == &win.winClient())
m_focused_window = 0;
2002-12-01 13:42:15 +00:00
} else if ((&(win.workspaceSig())) == changedsub) { // workspace signal
for (AtomHandlerContainerIt it= m_atomhandler.begin();
it != m_atomhandler.end(); ++it) {
if ((*it).first->update())
(*it).first->updateWorkspace(win);
}
2002-12-01 13:42:15 +00:00
} else {
#ifdef DEBUG
2002-12-01 13:42:15 +00:00
cerr<<__FILE__<<"("<<__LINE__<<"): WINDOW uncought signal from "<<&win<<endl;
#endif // DEBUG
2002-12-01 13:42:15 +00:00
}
2002-12-01 13:42:15 +00:00
} else if (typeid(*changedsub) == typeid(BScreen::ScreenSubject)) {
BScreen::ScreenSubject *subj = dynamic_cast<BScreen::ScreenSubject *>(changedsub);
BScreen &screen = subj->screen();
if ((&(screen.workspaceCountSig())) == changedsub) {
for (AtomHandlerContainerIt it= m_atomhandler.begin();
it != m_atomhandler.end(); ++it) {
if ((*it).first->update())
(*it).first->updateWorkspaceCount(screen);
2002-12-01 13:42:15 +00:00
}
} else if ((&(screen.workspaceNamesSig())) == changedsub) {
for (AtomHandlerContainerIt it= m_atomhandler.begin();
it != m_atomhandler.end(); ++it) {
if ((*it).first->update())
(*it).first->updateWorkspaceNames(screen);
2002-12-01 13:42:15 +00:00
}
} else if ((&(screen.currentWorkspaceSig())) == changedsub) {
for (AtomHandlerContainerIt it= m_atomhandler.begin();
it != m_atomhandler.end(); ++it) {
if ((*it).first->update())
(*it).first->updateCurrentWorkspace(screen);
2002-12-01 13:42:15 +00:00
}
} else if ((&(screen.workspaceAreaSig())) == changedsub) {
for (AtomHandlerContainerIt it= m_atomhandler.begin();
it != m_atomhandler.end(); ++it) {
if ((*it).first->update())
(*it).first->updateWorkarea(screen);
}
2002-12-01 13:42:15 +00:00
} else if ((&(screen.clientListSig())) == changedsub) {
for (AtomHandlerContainerIt it= m_atomhandler.begin();
it != m_atomhandler.end(); ++it) {
if ((*it).first->update())
(*it).first->updateClientList(screen);
2002-12-01 13:42:15 +00:00
}
}
2003-04-14 15:28:52 +00:00
} else if (typeid(*changedsub) == typeid(WinClient::WinClientSubj)) {
2003-04-14 15:28:52 +00:00
WinClient::WinClientSubj *subj = dynamic_cast<WinClient::WinClientSubj *>(changedsub);
WinClient &client = subj->winClient();
2003-07-04 14:06:20 +00:00
// TODO: don't assume it is diesig (need to fix as soon as another signal appears)
for (AtomHandlerContainerIt it= m_atomhandler.begin();
it != m_atomhandler.end(); ++it) {
if ((*it).first->update())
(*it).first->updateClientClose(client);
2003-07-04 14:06:20 +00:00
}
BScreen &screen = client.screen();
screen.removeClient(client);
// finaly send notify signal
screen.updateNetizenWindowDel(client.window());
2003-04-14 15:28:52 +00:00
2004-03-21 09:00:25 +00:00
// At this point, we trust that this client is no longer in the
// client list of its frame (but it still has reference to the frame)
// We also assume that any remaining active one is the last focused one
// This is where we revert focus on window close
// NOWHERE ELSE!!!
if (m_focused_window == &client)
unfocusWindow(client);
// failed to revert focus?
if (m_focused_window == &client)
m_focused_window = 0;
2002-12-01 13:42:15 +00:00
}
}
void Fluxbox::attachSignals(FluxboxWindow &win) {
2002-12-01 13:42:15 +00:00
win.hintSig().attach(this);
win.stateSig().attach(this);
win.workspaceSig().attach(this);
win.layerSig().attach(this);
2003-03-03 21:51:13 +00:00
win.dieSig().attach(this);
for (AtomHandlerContainerIt it= m_atomhandler.begin();
it != m_atomhandler.end(); ++it) {
(*it).first->setupFrame(win);
}
}
void Fluxbox::attachSignals(WinClient &winclient) {
winclient.dieSig().attach(this);
for (AtomHandlerContainerIt it= m_atomhandler.begin();
it != m_atomhandler.end(); ++it) {
(*it).first->setupClient(winclient);
2002-12-01 13:42:15 +00:00
}
2001-12-11 20:47:02 +00:00
}
BScreen *Fluxbox::searchScreen(Window window) {
2004-02-27 12:32:54 +00:00
ScreenList::iterator it = m_screen_list.begin();
2003-04-25 16:00:03 +00:00
ScreenList::iterator it_end = m_screen_list.end();
2002-12-01 13:42:15 +00:00
for (; it != it_end; ++it) {
2003-08-24 11:19:45 +00:00
if (*it && (*it)->rootWindow() == window)
2004-02-27 12:32:54 +00:00
return *it;
2002-12-01 13:42:15 +00:00
}
2003-04-14 15:28:52 +00:00
return 0;
2001-12-11 20:47:02 +00:00
}
2004-04-19 22:48:19 +00:00
AtomHandler* Fluxbox::getAtomHandler(const std::string &name) {
if ( name != "" ) {
for (AtomHandlerContainerIt it= m_atomhandler.begin();
it != m_atomhandler.end(); it++ ) {
if ( name == (*it).second )
return (*it).first;
}
2003-04-25 16:00:03 +00:00
}
return 0;
}
2004-04-19 22:48:19 +00:00
void Fluxbox::addAtomHandler(AtomHandler *atomh, const std::string &name) {
m_atomhandler[atomh]= name;;
2003-04-25 16:00:03 +00:00
}
void Fluxbox::removeAtomHandler(AtomHandler *atomh) {
for (AtomHandlerContainerIt it= m_atomhandler.begin();
it != m_atomhandler.end();
++it) {
if ((*it).first == atomh) {
2003-04-25 16:00:03 +00:00
m_atomhandler.erase(it);
return;
}
}
}
2001-12-11 20:47:02 +00:00
WinClient *Fluxbox::searchWindow(Window window) {
std::map<Window, WinClient *>::iterator it = m_window_search.find(window);
if (it != m_window_search.end())
return it->second;
std::map<Window, FluxboxWindow *>::iterator git = m_window_search_group.find(window);
return git == m_window_search_group.end() ? 0 : &git->second->winClient();
2001-12-11 20:47:02 +00:00
}
/* Not implemented until we know how it'll be used
* Recall that this refers to ICCCM groups, not fluxbox tabgroups
* See ICCCM 4.1.11 for details
*/
/*
WinClient *Fluxbox::searchGroup(Window window) {
2001-12-11 20:47:02 +00:00
}
*/
2001-12-11 20:47:02 +00:00
void Fluxbox::saveWindowSearch(Window window, WinClient *data) {
2003-04-25 16:00:03 +00:00
m_window_search[window] = data;
2001-12-11 20:47:02 +00:00
}
/* some windows relate to the whole group */
void Fluxbox::saveWindowSearchGroup(Window window, FluxboxWindow *data) {
m_window_search_group[window] = data;
}
2001-12-11 20:47:02 +00:00
void Fluxbox::saveGroupSearch(Window window, WinClient *data) {
m_group_search.insert(pair<Window, WinClient *>(window, data));
2001-12-11 20:47:02 +00:00
}
void Fluxbox::removeWindowSearch(Window window) {
2003-04-25 16:00:03 +00:00
m_window_search.erase(window);
2001-12-11 20:47:02 +00:00
}
void Fluxbox::removeWindowSearchGroup(Window window) {
m_window_search_group.erase(window);
}
2001-12-11 20:47:02 +00:00
void Fluxbox::removeGroupSearch(Window window) {
2003-04-25 16:00:03 +00:00
m_group_search.erase(window);
2001-12-11 20:47:02 +00:00
}
2003-04-25 16:00:03 +00:00
/// restarts fluxbox
2001-12-11 20:47:02 +00:00
void Fluxbox::restart(const char *prog) {
2002-12-01 13:42:15 +00:00
shutdown();
2001-12-11 20:47:02 +00:00
m_restarting = true;
2002-12-01 13:42:15 +00:00
if (prog) {
m_restart_argument = prog;
2002-12-01 13:42:15 +00:00
}
2001-12-11 20:47:02 +00:00
}
2003-04-25 16:00:03 +00:00
/// prepares fluxbox for a shutdown
void Fluxbox::shutdown() {
if (m_shutdown)
return;
m_shutdown = true;
2001-12-11 20:47:02 +00:00
2003-04-25 16:00:03 +00:00
XSetInputFocus(FbTk::App::instance()->display(), PointerRoot, None, CurrentTime);
2001-12-11 20:47:02 +00:00
2002-12-01 13:42:15 +00:00
//send shutdown to all screens
for_each(m_screen_list.begin(),
m_screen_list.end(), mem_fun(&BScreen::shutdown));
2003-08-24 11:19:45 +00:00
2003-12-04 21:31:02 +00:00
sync(false);
2001-12-11 20:47:02 +00:00
}
2003-04-25 16:00:03 +00:00
/// saves resources
void Fluxbox::save_rc() {
2004-06-07 11:46:05 +00:00
_FB_USES_NLS;
2002-12-01 13:42:15 +00:00
XrmDatabase new_blackboxrc = 0;
2002-12-01 13:42:15 +00:00
char rc_string[1024];
2001-12-11 20:47:02 +00:00
2002-12-01 13:42:15 +00:00
string dbfile(getRcFilename());
2004-01-21 13:36:09 +00:00
if (!dbfile.empty()) {
2002-12-01 13:42:15 +00:00
m_resourcemanager.save(dbfile.c_str(), dbfile.c_str());
m_screen_rm.save(dbfile.c_str(), dbfile.c_str());
} else
2004-06-07 11:46:05 +00:00
cerr<<_FBTEXT(Fluxbox, BadRCFile, "rc filename is invalid!", "Bad settings file")<<endl;
2003-04-25 16:00:03 +00:00
ScreenList::iterator it = m_screen_list.begin();
ScreenList::iterator it_end = m_screen_list.end();
2002-12-01 13:42:15 +00:00
//Save screen resources
for (; it != it_end; ++it) {
BScreen *screen = *it;
2003-05-15 12:00:46 +00:00
int screen_number = screen->screenNumber();
2002-12-01 13:42:15 +00:00
// these are static, but may not be saved in the users resource file,
// writing these resources will allow the user to edit them at a later
// time... but loading the defaults before saving allows us to rewrite the
// users changes...
2001-12-11 20:47:02 +00:00
2002-12-01 13:42:15 +00:00
// write out the users workspace names
sprintf(rc_string, "session.screen%d.workspaceNames: ", screen_number);
string workspaces_string(rc_string);
2002-02-17 18:43:30 +00:00
2002-12-01 13:42:15 +00:00
for (unsigned int workspace=0; workspace < screen->getCount(); workspace++) {
if (screen->getWorkspace(workspace)->name().size()!=0)
workspaces_string.append(screen->getWorkspace(workspace)->name());
else
workspaces_string.append("Null");
workspaces_string.append(",");
}
2002-01-21 02:04:23 +00:00
2002-12-01 13:42:15 +00:00
XrmPutLineResource(&new_blackboxrc, workspaces_string.c_str());
2002-12-01 13:42:15 +00:00
}
2001-12-11 20:47:02 +00:00
2002-12-01 13:42:15 +00:00
XrmDatabase old_blackboxrc = XrmGetFileDatabase(dbfile.c_str());
2001-12-11 20:47:02 +00:00
2002-12-01 13:42:15 +00:00
XrmMergeDatabases(new_blackboxrc, &old_blackboxrc); //merge database together
XrmPutFileDatabase(old_blackboxrc, dbfile.c_str());
XrmDestroyDatabase(old_blackboxrc);
2002-08-13 21:19:00 +00:00
#ifdef DEBUG
cerr<<__FILE__<<"("<<__LINE__<<"): ------------ SAVING DONE"<<endl;
2002-08-13 21:19:00 +00:00
#endif // DEBUG
2001-12-11 20:47:02 +00:00
}
2003-04-25 16:00:03 +00:00
/// @return filename of resource file
string Fluxbox::getRcFilename() {
2004-01-21 13:36:09 +00:00
if (m_rc_file.empty()) { // set default filename
2003-05-11 22:19:17 +00:00
string defaultfile(getenv("HOME") + string("/.") + m_RC_PATH + string("/") + m_RC_INIT_FILE);
2002-12-01 13:42:15 +00:00
return defaultfile;
}
2002-01-11 09:26:33 +00:00
2003-04-25 16:00:03 +00:00
return m_rc_file;
2001-12-11 20:47:02 +00:00
}
2003-04-25 16:00:03 +00:00
/// Provides default filename of data file
2002-05-29 06:22:31 +00:00
void Fluxbox::getDefaultDataFilename(char *name, string &filename) {
2003-05-11 22:19:17 +00:00
filename = string(getenv("HOME") + string("/.") + m_RC_PATH + string("/") + name);
2002-05-29 06:22:31 +00:00
}
2003-04-25 16:00:03 +00:00
/// loads resources
void Fluxbox::load_rc() {
2004-06-07 11:46:05 +00:00
_FB_USES_NLS;
2002-12-01 13:42:15 +00:00
//get resource filename
string dbfile(getRcFilename());
2004-01-21 13:36:09 +00:00
if (!dbfile.empty()) {
2002-12-01 13:42:15 +00:00
if (!m_resourcemanager.load(dbfile.c_str())) {
2004-06-07 11:46:05 +00:00
cerr<<_FBTEXT(Fluxbox, CantLoadRCFile, "Failed to load database", "Failed trying to read rc file")<<":"<<dbfile<<endl;
cerr<<_FBTEXT(Fluxbox, CantLoadRCFileTrying, "Retrying with", "Retrying rc file loading with (the following file)")<<": "<<DEFAULT_INITFILE<<endl;
2002-12-01 13:42:15 +00:00
if (!m_resourcemanager.load(DEFAULT_INITFILE))
2004-06-07 11:46:05 +00:00
cerr<<_FBTEXT(Fluxbox, CantLoadRCFile, "Failed to load database", "")<<": "<<DEFAULT_INITFILE<<endl;
2002-12-01 13:42:15 +00:00
}
} else {
if (!m_resourcemanager.load(DEFAULT_INITFILE))
2004-06-07 11:46:05 +00:00
cerr<<_FBTEXT(Fluxbox, CantLoadRCFile, "Failed to load database", "")<<": "<<DEFAULT_INITFILE<<endl;
2002-12-01 13:42:15 +00:00
}
if (m_rc_menufile->empty())
2003-12-19 00:35:08 +00:00
m_rc_menufile.setDefaultValue();
if (FbTk::Transparent::haveComposite())
FbTk::Transparent::usePseudoTransparent(*m_rc_pseudotrans);
2004-01-21 13:36:09 +00:00
if (!m_rc_slitlistfile->empty()) {
2002-12-01 13:42:15 +00:00
*m_rc_slitlistfile = StringUtil::expandFilename(*m_rc_slitlistfile);
} else {
string filename;
getDefaultDataFilename("slitlist", filename);
m_rc_slitlistfile.setFromString(filename.c_str());
}
if (*m_rc_colors_per_channel < 2)
*m_rc_colors_per_channel = 2;
else if (*m_rc_colors_per_channel > 6)
*m_rc_colors_per_channel = 6;
if (m_rc_stylefile->empty())
2002-12-01 13:42:15 +00:00
*m_rc_stylefile = DEFAULTSTYLE;
2002-12-01 13:42:15 +00:00
if (!Workspace::loadGroups(*m_rc_groupfile)) {
2004-06-07 11:46:05 +00:00
cerr<<_FBTEXT(Fluxbox, CantLoadGroupFile, "Failed to load groupfile", "Couldn't load the groupfile")<<": "<<*m_rc_groupfile<<endl;
2002-12-01 13:42:15 +00:00
}
}
2003-04-15 12:22:52 +00:00
void Fluxbox::load_rc(BScreen &screen) {
2002-12-01 13:42:15 +00:00
//get resource filename
2004-06-07 11:46:05 +00:00
_FB_USES_NLS;
2002-12-01 13:42:15 +00:00
string dbfile(getRcFilename());
2002-12-01 13:42:15 +00:00
XrmDatabaseHelper database;
2002-12-01 13:42:15 +00:00
database = XrmGetFileDatabase(dbfile.c_str());
if (database==0)
database = XrmGetFileDatabase(DEFAULT_INITFILE);
2002-12-01 13:42:15 +00:00
XrmValue value;
char *value_type, name_lookup[1024], class_lookup[1024];
2003-05-15 12:00:46 +00:00
int screen_number = screen.screenNumber();
2002-12-01 13:42:15 +00:00
2003-04-15 12:22:52 +00:00
screen.removeWorkspaceNames();
2002-12-01 13:42:15 +00:00
sprintf(name_lookup, "session.screen%d.workspaceNames", screen_number);
sprintf(class_lookup, "Session.Screen%d.WorkspaceNames", screen_number);
if (XrmGetResource(*database, name_lookup, class_lookup, &value_type,
&value)) {
#ifdef DEBUG
2003-04-15 12:22:52 +00:00
cerr<<__FILE__<<"("<<__FUNCTION__<<"): Workspaces="<<
screen.getNumberOfWorkspaces()<<endl;
#endif // DEBUG
2002-12-01 13:42:15 +00:00
char *search = StringUtil::strdup(value.addr);
2002-12-01 13:42:15 +00:00
int i;
2003-04-15 12:22:52 +00:00
for (i = 0; i < screen.getNumberOfWorkspaces(); i++) {
2002-12-01 13:42:15 +00:00
char *nn;
2002-12-01 13:42:15 +00:00
if (! i) nn = strtok(search, ",");
else nn = strtok(0, ",");
2002-12-01 13:42:15 +00:00
if (nn)
screen.addWorkspaceName(nn);
2002-12-01 13:42:15 +00:00
else break;
2002-12-01 13:42:15 +00:00
}
delete [] search;
}
FbTk::Image::removeAllSearchPaths();
sprintf(name_lookup, "session.screen%d.imageSearchPath", screen_number);
sprintf(class_lookup, "Session.Screen%d.imageSearchPath", screen_number);
if (XrmGetResource(*database, name_lookup, class_lookup, &value_type,
&value) && value.addr) {
std::vector<std::string> paths;
StringUtil::stringtok(paths, value.addr, ", ");
for (unsigned int i=0; i<paths.size(); ++i)
FbTk::Image::addSearchPath(paths[i]);
}
2004-01-21 13:36:09 +00:00
if (!dbfile.empty()) {
if (!m_screen_rm.load(dbfile.c_str())) {
2004-06-07 11:46:05 +00:00
cerr<<_FBTEXT(Fluxbox, CantLoadRCFile, "Failed to load database", "Failed trying to read rc file")<<":"<<dbfile<<endl;
cerr<<_FBTEXT(Fluxbox, CantLoadRCFileTrying, "Retrying with", "Retrying rc file loading with (the following file)")<<": "<<DEFAULT_INITFILE<<endl;
if (!m_screen_rm.load(DEFAULT_INITFILE))
2004-06-07 11:46:05 +00:00
cerr<<_FBTEXT(Fluxbox, CantLoadRCFile, "Failed to load database", "")<<": "<<DEFAULT_INITFILE<<endl;
}
} else {
if (!m_screen_rm.load(DEFAULT_INITFILE))
2004-06-07 11:46:05 +00:00
cerr<<_FBTEXT(Fluxbox, CantLoadRCFile, "Failed to load database", "")<<": "<<DEFAULT_INITFILE<<endl;
}
2001-12-11 20:47:02 +00:00
}
2003-04-15 12:22:52 +00:00
void Fluxbox::loadRootCommand(BScreen &screen) {
2002-12-01 13:42:15 +00:00
string dbfile(getRcFilename());
2002-12-02 23:49:56 +00:00
XrmDatabaseHelper database(dbfile.c_str());
if (!*database)
2002-12-01 13:42:15 +00:00
database = XrmGetFileDatabase(DEFAULT_INITFILE);
XrmValue value;
char *value_type, name_lookup[1024], class_lookup[1024];
2003-05-15 12:00:46 +00:00
sprintf(name_lookup, "session.screen%d.rootCommand", screen.screenNumber());
sprintf(class_lookup, "Session.Screen%d.RootCommand", screen.screenNumber());
2002-12-02 23:49:56 +00:00
if (XrmGetResource(*database, name_lookup, class_lookup, &value_type,
&value)) {
2003-04-15 12:22:52 +00:00
screen.saveRootCommand(value.addr==0 ? "": value.addr);
2002-12-01 13:42:15 +00:00
} else
screen.saveRootCommand("");
}
2002-01-11 09:26:33 +00:00
void Fluxbox::reload_rc() {
2002-12-01 13:42:15 +00:00
load_rc();
reconfigure();
2001-12-11 20:47:02 +00:00
}
void Fluxbox::reconfigure() {
2003-04-25 16:00:03 +00:00
m_reconfigure_wait = true;
m_reconfig_timer.start();
2001-12-11 20:47:02 +00:00
}
void Fluxbox::real_reconfigure() {
2001-12-11 20:47:02 +00:00
2002-12-01 13:42:15 +00:00
XrmDatabase new_blackboxrc = (XrmDatabase) 0;
2001-12-11 20:47:02 +00:00
2002-12-01 13:42:15 +00:00
string dbfile(getRcFilename());
XrmDatabase old_blackboxrc = XrmGetFileDatabase(dbfile.c_str());
2001-12-11 20:47:02 +00:00
2002-12-01 13:42:15 +00:00
XrmMergeDatabases(new_blackboxrc, &old_blackboxrc);
XrmPutFileDatabase(old_blackboxrc, dbfile.c_str());
2002-12-01 13:42:15 +00:00
if (old_blackboxrc)
XrmDestroyDatabase(old_blackboxrc);
ScreenList::iterator screen_it = m_screen_list.begin();
2004-04-05 18:31:51 +00:00
ScreenList::iterator screen_it_end = m_screen_list.end();
for (; screen_it != screen_it_end; ++screen_it)
load_rc(*(*screen_it));
2003-08-24 11:19:45 +00:00
// reconfigure all screens
for_each(m_screen_list.begin(), m_screen_list.end(), mem_fun(&BScreen::reconfigure));
2003-05-13 00:20:49 +00:00
2002-12-01 13:42:15 +00:00
//reconfigure keys
2003-04-25 16:00:03 +00:00
m_key->reconfigure(StringUtil::expandFilename(*m_rc_keyfile).c_str());
2001-12-11 20:47:02 +00:00
}
BScreen *Fluxbox::findScreen(int id) {
ScreenList::iterator it = m_screen_list.begin();
ScreenList::iterator it_end = m_screen_list.end();
for (; it != it_end; ++it) {
if ((*it)->screenNumber() == id)
break;
}
if (it == m_screen_list.end())
return 0;
return *it;
}
2001-12-11 20:47:02 +00:00
2003-05-13 00:20:49 +00:00
bool Fluxbox::menuTimestampsChanged() const {
std::list<MenuTimestamp *>::const_iterator it = m_menu_timestamps.begin();
std::list<MenuTimestamp *>::const_iterator it_end = m_menu_timestamps.end();
for (; it != it_end; ++it) {
time_t timestamp = FbTk::FileUtil::getLastStatusChangeTimestamp((*it)->filename.c_str());
2002-12-01 13:42:15 +00:00
if (timestamp >= 0) {
if (timestamp != (*it)->timestamp)
2003-05-13 00:20:49 +00:00
return true;
2002-12-01 13:42:15 +00:00
} else
2003-05-13 00:20:49 +00:00
return true;
2002-12-01 13:42:15 +00:00
}
2003-05-13 00:20:49 +00:00
// no timestamp changed
return false;
}
void Fluxbox::checkMenu() {
if (menuTimestampsChanged())
rereadMenu();
2001-12-11 20:47:02 +00:00
}
2004-01-11 16:10:51 +00:00
void Fluxbox::hideExtraMenus(BScreen &screen) {
#ifdef USE_TOOLBAR
// hide toolbar that matches screen
for (size_t toolbar = 0; toolbar < m_toolbars.size(); ++toolbar) {
if (&(m_toolbars[toolbar]->screen()) == &screen)
m_toolbars[toolbar]->menu().hide();
}
#endif // USE_TOOLBAR
}
2001-12-11 20:47:02 +00:00
void Fluxbox::rereadMenu(bool show_after_reread) {
2003-04-25 16:00:03 +00:00
m_reread_menu_wait = true;
m_show_menu_after_reread = show_after_reread;
m_reconfig_timer.start();
2001-12-11 20:47:02 +00:00
}
void Fluxbox::real_rereadMenu() {
clearMenuFilenames();
for_each(m_screen_list.begin(),
m_screen_list.end(),
mem_fun(&BScreen::rereadMenu));
if(m_show_menu_after_reread) {
FbCommands::ShowRootMenuCmd showcmd;
showcmd.execute();
m_show_menu_after_reread = false;
}
2001-12-11 20:47:02 +00:00
}
void Fluxbox::saveMenuFilename(const char *filename) {
2003-04-25 16:00:03 +00:00
if (filename == 0)
return;
bool found = false;
2001-12-11 20:47:02 +00:00
2003-04-25 16:00:03 +00:00
std::list<MenuTimestamp *>::iterator it = m_menu_timestamps.begin();
std::list<MenuTimestamp *>::iterator it_end = m_menu_timestamps.end();
2002-12-01 13:42:15 +00:00
for (; it != it_end; ++it) {
2003-04-25 16:00:03 +00:00
if ((*it)->filename == filename) {
found = true;
break;
2003-04-25 16:00:03 +00:00
}
2002-12-01 13:42:15 +00:00
}
2001-12-11 20:47:02 +00:00
2002-12-01 13:42:15 +00:00
if (! found) {
time_t timestamp = FbTk::FileUtil::getLastStatusChangeTimestamp(filename);
2001-12-11 20:47:02 +00:00
if (timestamp >= 0) {
2002-12-01 13:42:15 +00:00
MenuTimestamp *ts = new MenuTimestamp;
2001-12-11 20:47:02 +00:00
2003-04-25 16:00:03 +00:00
ts->filename = filename;
ts->timestamp = timestamp;
2001-12-11 20:47:02 +00:00
2003-04-25 16:00:03 +00:00
m_menu_timestamps.push_back(ts);
2002-12-01 13:42:15 +00:00
}
}
2001-12-11 20:47:02 +00:00
}
2003-05-13 00:20:49 +00:00
void Fluxbox::clearMenuFilenames() {
while(!m_menu_timestamps.empty()) {
delete m_menu_timestamps.back();
m_menu_timestamps.pop_back();
}
2003-05-13 00:20:49 +00:00
}
2001-12-11 20:47:02 +00:00
void Fluxbox::timed_reconfigure() {
2003-04-25 16:00:03 +00:00
if (m_reconfigure_wait)
2002-12-01 13:42:15 +00:00
real_reconfigure();
2001-12-11 20:47:02 +00:00
2003-04-25 16:00:03 +00:00
if (m_reread_menu_wait)
2002-12-01 13:42:15 +00:00
real_rereadMenu();
2001-12-11 20:47:02 +00:00
2003-04-25 16:00:03 +00:00
m_reconfigure_wait = m_reread_menu_wait = false;
2001-12-11 20:47:02 +00:00
}
// set focused window
void Fluxbox::setFocusedWindow(WinClient *client) {
// already focused
if (m_focused_window == client) {
#ifdef DEBUG
cerr<<"Focused window already win"<<endl;
#endif // DEBUG
return;
}
#ifdef DEBUG
cerr<<"Setting Focused window = "<<client<<endl;
2004-07-14 23:39:29 +00:00
if (client != 0 && client->fbwindow() != 0)
cerr<<"title: "<<client->fbwindow()->title()<<endl;
cerr<<"Current Focused window = "<<m_focused_window<<endl;
cerr<<"------------------"<<endl;
#endif // DEBUG
2002-12-01 13:42:15 +00:00
BScreen *old_screen = 0, *screen = 0;
WinClient *old_client = 0;
2003-04-25 16:00:03 +00:00
if (m_focused_window != 0) {
// check if m_focused_window is valid
bool found = false;
std::map<Window, WinClient *>::iterator it = m_window_search.begin();
std::map<Window, WinClient *>::iterator it_end = m_window_search.end();
for (; it != it_end; ++it) {
if (it->second == m_focused_window) {
// we found it, end loop
found = true;
break;
}
}
if (!found) {
m_focused_window = 0;
} else {
old_client = m_focused_window;
old_screen = &old_client->screen();
2001-12-11 20:47:02 +00:00
if (old_client->fbwindow()) {
FluxboxWindow *old_win = old_client->fbwindow();
if (!client || client->fbwindow() != old_win)
old_win->setFocusFlag(false);
}
}
2002-12-01 13:42:15 +00:00
}
if (client && client->fbwindow() && !client->fbwindow()->isIconic()) {
FluxboxWindow *win = client->fbwindow();
2002-12-01 13:42:15 +00:00
// make sure we have a valid win pointer with a valid screen
ScreenList::iterator winscreen =
2003-04-25 16:00:03 +00:00
std::find(m_screen_list.begin(), m_screen_list.end(),
&client->screen());
2003-04-25 16:00:03 +00:00
if (winscreen == m_screen_list.end()) {
m_focused_window = 0; // the window pointer wasn't valid, mark no window focused
2002-12-01 13:42:15 +00:00
} else {
screen = *winscreen;
m_focused_window = client; // update focused window
win->setCurrentClient(*client, false); // don't setinputfocus
2003-04-25 16:00:03 +00:00
win->setFocusFlag(true); // set focus flag
2002-12-01 13:42:15 +00:00
}
2002-12-01 13:42:15 +00:00
} else
2003-04-25 16:00:03 +00:00
m_focused_window = 0;
2002-12-01 13:42:15 +00:00
2003-06-25 06:02:53 +00:00
if (screen != 0) {
2002-12-01 13:42:15 +00:00
screen->updateNetizenWindowFocus();
for (AtomHandlerContainerIt it= m_atomhandler.begin();
it != m_atomhandler.end(); it++) {
(*it).first->updateFocusedWindow(*screen, (m_focused_window ?
2004-06-13 11:01:47 +00:00
m_focused_window->window() :
0));
}
}
2002-12-01 13:42:15 +00:00
if (old_screen && old_screen != screen) {
2002-12-01 13:42:15 +00:00
old_screen->updateNetizenWindowFocus();
for (AtomHandlerContainerIt it= m_atomhandler.begin();
it != m_atomhandler.end(); it++)
(*it).first->updateFocusedWindow(*old_screen, 0);
}
2001-12-11 20:47:02 +00:00
}
2003-05-04 23:38:06 +00:00
/**
* This function is called whenever we aren't quite sure what
* focus is meant to be, it'll make things right ;-)
* last_focused is set to something if we want to make use of the
* previously focused window (it must NOT be set focused now, it
2003-05-04 23:38:06 +00:00
* is probably dying).
*
* ignore_event means that it ignores the given event until
* it gets a focusIn
2003-05-04 23:38:06 +00:00
*/
2003-12-30 20:56:41 +00:00
void Fluxbox::revertFocus(BScreen &screen) {
2003-05-04 23:38:06 +00:00
// Relevant resources:
// resource.focus_last = whether we focus last focused when changing workspace
2003-12-19 00:35:08 +00:00
// BScreen::FocusModel = sloppy, click, whatever
2003-12-30 20:56:41 +00:00
WinClient *next_focus = screen.getLastFocusedWindow(screen.currentWorkspaceID());
2003-05-04 23:38:06 +00:00
2003-05-11 23:44:09 +00:00
// if setting focus fails, or isn't possible, fallback correctly
if (!(next_focus && next_focus->fbwindow() &&
2003-12-30 20:56:41 +00:00
next_focus->fbwindow()->setCurrentClient(*next_focus, true))) {
setFocusedWindow(0); // so we don't get dangling m_focused_window pointer
switch (screen.getFocusModel()) {
2003-12-19 00:35:08 +00:00
case BScreen::SLOPPYFOCUS:
case BScreen::SEMISLOPPYFOCUS:
XSetInputFocus(FbTk::App::instance()->display(),
2003-05-04 23:38:06 +00:00
PointerRoot, None, CurrentTime);
break;
2003-12-19 00:35:08 +00:00
case BScreen::CLICKTOFOCUS:
screen.rootWindow().setInputFocus(RevertToPointerRoot, CurrentTime);
2003-05-04 23:38:06 +00:00
break;
}
}
}
2004-03-21 09:00:25 +00:00
/*
* Like revertFocus, but specifically related to this window (transients etc)
* if full_revert, we fallback to a full revertFocus if we can't find anything
* local to the client.
* If unfocus_frame is true, we won't focus anything in the same frame
* as the client.
2004-03-21 09:00:25 +00:00
*
* So, we first prefer to choose a transient parent, then the last
* client in this window, and if no luck (or unfocus_frame), then
2004-03-21 09:00:25 +00:00
* we just use the normal revertFocus on the screen.
*
* assumption: client has focus
*/
void Fluxbox::unfocusWindow(WinClient &client, bool full_revert, bool unfocus_frame) {
// go up the transient tree looking for a focusable window
FluxboxWindow *fbwin = client.fbwindow();
if (fbwin == 0)
2004-03-21 09:00:25 +00:00
unfocus_frame = false;
WinClient *trans_parent = client.transientFor();
while (trans_parent) {
if (trans_parent->fbwindow() && // can't focus if no fbwin
(!unfocus_frame || trans_parent->fbwindow() != fbwin) && // can't be this window
trans_parent->fbwindow()->isVisible() &&
trans_parent->fbwindow()->setCurrentClient(*trans_parent, m_focused_window == &client)) {
return;
}
trans_parent = trans_parent->transientFor();
}
if (fbwin == 0)
return; // nothing more we can do
BScreen &screen = fbwin->screen();
if (!unfocus_frame) {
WinClient *last_focus = screen.getLastFocusedWindow(*fbwin, &client);
if (last_focus != 0 &&
2004-03-21 09:00:25 +00:00
fbwin->setCurrentClient(*last_focus, m_focused_window == &client)) {
return;
}
}
if (full_revert && m_focused_window == &client)
revertFocus(screen);
}
2003-05-04 23:38:06 +00:00
void Fluxbox::watchKeyRelease(BScreen &screen, unsigned int mods) {
if (mods == 0) {
cerr<<"WARNING: attempt to grab without modifiers!"<<endl;
return;
}
m_watching_screen = &screen;
2003-04-25 16:00:03 +00:00
m_watch_keyrelease = mods;
XGrabKeyboard(FbTk::App::instance()->display(),
screen.rootWindow().window(), True,
GrabModeAsync, GrabModeAsync, CurrentTime);
}