add SetTitle and SetTitleDialog key commands

This commit is contained in:
Mark Tiefenbruck 2008-08-17 04:10:17 -07:00
parent 72fd5e03a4
commit a23778a44d
18 changed files with 353 additions and 199 deletions

View file

@ -1,5 +1,8 @@
(Format: Year/Month/Day)
Changes for 1.1
*08/08/17:
* Add new key commands SetTitle and SetTitleDialog (thanks Matteo Galiazzo)
CommandDialog.cc/hh TextDialog.cc/hh CurrentWindowCmd.cc/hh Makefile.am
*08/08/06:
* Created manual for fluxbox-remote (Mark)
doc/asciidoc/fluxbox-remote.txt doc/fluxbox-remote.1

View file

@ -5,6 +5,7 @@
[iconify]
[raise]
[lower]
[settitledialog]
[sendto]
[layer]
[alpha]

View file

@ -215,6 +215,7 @@ $set 16 #Windowmenu
9 Stick
10 Kill
11 Use Defaults
12 Set Window Title
$set 17 #Workspace

View file

@ -215,6 +215,7 @@ $set 16 #Windowmenu
9 Stick
10 Kill
11 Use Defaults
12 Set Window Title
$set 17 #Workspace

View file

@ -215,6 +215,7 @@ $set 16 #Windowmenu
9 Stick
10 Kill
11 Use Defaults
12 Set Window Title
$set 17 #Workspace

View file

@ -215,6 +215,7 @@ $set 16 #Windowmenu
9 Stick
10 Kill
11 Use Defaults
12 Set Window Title
$set 17 #Workspace

View file

@ -215,6 +215,7 @@ $set 16 #Windowmenu
9 Stick
10 Kill
11 Use Defaults
12 Set Window Title
$set 17 #Workspace

View file

@ -215,6 +215,7 @@ $set 16 #Windowmenu
9 Stick
10 Kill
11 Use Defaults
12 Set Window Title
$set 17 #Workspace

View file

@ -215,6 +215,7 @@ $set 16 #Windowmenu
9 Stick
10 Kill
11 Use Defaults
12 Set Window Title
$set 17 #Workspace

View file

@ -209,6 +209,7 @@ enum {
WindowmenuStick = 9,
WindowmenuKill = 10,
WindowmenuDefaultAlpha = 11,
WindowmenuSetTitle = 12,
WorkspaceSet = 17,
WorkspaceDefaultNameFormat = 1,

View file

@ -22,24 +22,16 @@
#include "CommandDialog.hh"
#include "Screen.hh"
#include "FbWinFrameTheme.hh"
#include "WinClient.hh"
#include "FbTk/CommandParser.hh"
#include "FocusControl.hh"
#include "fluxbox.hh"
#include "FbTk/ImageControl.hh"
#include "FbTk/EventManager.hh"
#include "FbTk/StringUtil.hh"
#include "FbTk/KeyUtil.hh"
#include "FbTk/App.hh"
#include <X11/keysym.h>
#include <X11/Xutil.h>
#include <algorithm>
#include <memory>
#include <stdexcept>
#include <vector>
using std::string;
using std::vector;
@ -47,115 +39,31 @@ using std::auto_ptr;
using std::less;
using std::out_of_range;
CommandDialog::CommandDialog(BScreen &screen,
const string &title, const string precommand) :
FbTk::FbWindow(screen.rootWindow().screenNumber(), 0, 0, 200, 1, ExposureMask),
m_textbox(*this, screen.focusedWinFrameTheme()->font(), ""),
m_label(*this, screen.focusedWinFrameTheme()->font(), title),
m_gc(m_textbox),
m_screen(screen),
m_move_x(0),
m_move_y(0),
m_pixmap(0),
m_precommand(precommand) {
init();
CommandDialog::CommandDialog(BScreen &screen, const string &title,
const string precommand) :
TextDialog(screen, title),
m_precommand(precommand) { }
}
CommandDialog::~CommandDialog() {
FbTk::EventManager::instance()->remove(*this);
hide();
if (m_pixmap != 0)
m_screen.imageControl().removeImage(m_pixmap);
}
void CommandDialog::setText(const string &text) {
m_textbox.setText(text);
}
void CommandDialog::show() {
FbTk::FbWindow::show();
m_textbox.setInputFocus();
m_label.clear();
Fluxbox::instance()->setShowingDialog(true);
// resize to correct width, which should be the width of label text
// no need to truncate label text in this dialog
// but if label text size < 200 we set 200
if (m_label.textWidth() < 200)
return;
else {
resize(m_label.textWidth(), height());
updateSizes();
render();
}
}
void CommandDialog::hide() {
FbTk::FbWindow::hide();
Fluxbox::instance()->setShowingDialog(false);
}
void CommandDialog::exposeEvent(XExposeEvent &event) {
if (event.window == window())
clearArea(event.x, event.y, event.width, event.height);
}
void CommandDialog::buttonPressEvent(XButtonEvent &event) {
m_textbox.setInputFocus();
m_move_x = event.x_root - x();
m_move_y = event.y_root - y();
}
void CommandDialog::handleEvent(XEvent &event) {
if (event.type == ConfigureNotify && event.xconfigure.window != window()) {
moveResize(event.xconfigure.x, event.xconfigure.y,
event.xconfigure.width, event.xconfigure.height);
} else if (event.type == DestroyNotify)
delete this;
}
void CommandDialog::motionNotifyEvent(XMotionEvent &event) {
int new_x = event.x_root - m_move_x;
int new_y = event.y_root - m_move_y;
move(new_x, new_y);
}
void CommandDialog::keyPressEvent(XKeyEvent &event) {
unsigned int state = FbTk::KeyUtil::instance().isolateModifierMask(event.state);
if (state)
return;
KeySym ks;
char keychar;
XLookupString(&event, &keychar, 1, &ks, 0);
if (ks == XK_Return) {
// create Command<void> from line
auto_ptr<FbTk::Command<void> > cmd(FbTk::CommandParser<void>::instance().parse(m_precommand + m_textbox.text()));
if (cmd.get())
cmd->execute();
// post execute
if (*m_postcommand != 0)
m_postcommand->execute();
delete this; // end this
} else if (ks == XK_Escape)
delete this; // end this
else if (ks == XK_Tab) {
// try to expand a command
tabComplete();
}
void CommandDialog::exec(const std::string &text){
// create Command<void> from line
auto_ptr<FbTk::Command<void> > cmd(FbTk::CommandParser<void>::instance().parse(m_precommand + text));
if (cmd.get())
cmd->execute();
// post execute
if (*m_postcommand != 0)
m_postcommand->execute();
}
void CommandDialog::tabComplete() {
try {
string::size_type first = m_textbox.text().find_last_not_of("ABCDEFGHIJKLMNOPQRSTUVWXYZ"
"abcdefghijklmnopqrstuvwxyz"
"0123456789",
m_textbox.cursorPosition());
"abcdefghijklmnopqrstuvwxyz"
"0123456789", m_textbox.cursorPosition());
if (first == string::npos)
first = 0;
string prefix = FbTk::StringUtil::toLower(m_textbox.text().substr(first, m_textbox.cursorPosition()));
string prefix = FbTk::StringUtil::toLower(m_textbox.text().substr(first,
m_textbox.cursorPosition()));
if (prefix.empty()) {
XBell(FbTk::App::instance()->display(), 0);
return;
@ -181,59 +89,3 @@ void CommandDialog::tabComplete() {
XBell(FbTk::App::instance()->display(), 0);
}
}
void CommandDialog::render() {
Pixmap tmp = m_pixmap;
if (!m_screen.focusedWinFrameTheme()->iconbarTheme().texture().usePixmap()) {
m_label.setBackgroundColor(m_screen.focusedWinFrameTheme()->iconbarTheme().texture().color());
m_pixmap = 0;
} else {
m_pixmap = m_screen.imageControl().renderImage(m_label.width(), m_label.height(),
m_screen.focusedWinFrameTheme()->iconbarTheme().texture());
m_label.setBackgroundPixmap(m_pixmap);
}
if (tmp)
m_screen.imageControl().removeImage(tmp);
}
void CommandDialog::init() {
// setup label
// we listen to motion notify too
m_label.setEventMask(m_label.eventMask() | ButtonPressMask | ButtonMotionMask);
m_label.setGC(m_screen.focusedWinFrameTheme()->iconbarTheme().text().textGC());
m_label.show();
// setup text box
FbTk::Color white("white", m_textbox.screenNumber());
m_textbox.setBackgroundColor(white);
FbTk::Color black("black", m_textbox.screenNumber());
m_gc.setForeground(black);
m_textbox.setGC(m_gc.gc());
m_textbox.show();
// setup this window
setBorderWidth(1);
setBackgroundColor(white);
// move to center of the screen
move((m_screen.width() - width())/2, (m_screen.height() - height())/2);
updateSizes();
resize(width(), m_textbox.height() + m_label.height());
render();
// we need ConfigureNotify from children
FbTk::EventManager::instance()->addParent(*this, *this);
}
void CommandDialog::updateSizes() {
m_label.moveResize(0, 0,
width(), m_textbox.font().height() + 2);
m_textbox.moveResize(2, m_label.height(),
width() - 4, m_textbox.font().height() + 2);
}

View file

@ -23,26 +23,20 @@
#ifndef RUNCOMMANDDIALOG_HH
#define RUNCOMMANDDIALOG_HH
#include "FbTk/TextBox.hh"
#include "FbTk/TextButton.hh"
#include "FbTk/GContext.hh"
#include "TextDialog.hh"
#include "FbTk/RefCount.hh"
class BScreen;
class Command;
/**
* Displays a fluxbox command dialog which executes fluxbox
* action commands.
*/
class CommandDialog: public FbTk::FbWindow, public FbTk::EventHandler {
class CommandDialog: public TextDialog {
public:
CommandDialog(BScreen &screen, const std::string &title,
const std::string pre_command = "");
virtual ~CommandDialog();
/// Sets the entry text.
void setText(const std::string &text);
/**
* Sets the command to be executed after the command is done.
* @param postcommand the command.
@ -50,32 +44,14 @@ public:
void setPostCommand(FbTk::RefCount<FbTk::Command<void> > &postcommand) {
m_postcommand = postcommand;
}
void show();
void hide();
void exposeEvent(XExposeEvent &event);
void motionNotifyEvent(XMotionEvent &event);
void buttonPressEvent(XButtonEvent &event);
void handleEvent(XEvent &event);
void keyPressEvent(XKeyEvent &event);
protected:
/// expand the current word, using the history as a references
virtual void tabComplete();
private:
void init();
void render();
void updateSizes();
/// expand the current word, using the history as a references
void tabComplete();
void exec(const std::string &string);
FbTk::TextBox m_textbox; //< entry field
FbTk::TextButton m_label; //< text in the titlebar
FbTk::GContext m_gc;
/// command to do after the first command was issued (like reconfigure)
FbTk::RefCount<FbTk::Command<void> > m_postcommand;
BScreen &m_screen;
int m_move_x, m_move_y;
Pixmap m_pixmap;
/// command to be used before the text (usefull for setting workspace name)
const std::string m_precommand;
};

View file

@ -27,10 +27,12 @@
#include "Window.hh"
#include "WindowCmd.hh"
#include "Screen.hh"
#include "TextDialog.hh"
#include "WinClient.hh"
#include "FocusControl.hh"
#include "FbTk/CommandParser.hh"
#include "FbTk/I18n.hh"
#include "FbTk/stringstream.hh"
#include "FbTk/StringUtil.hh"
@ -483,7 +485,6 @@ void ResizeToCmd::real_execute() {
REGISTER_COMMAND(fullscreen, FullscreenCmd, void);
FullscreenCmd::FullscreenCmd() { }
void FullscreenCmd::real_execute() {
fbwindow().setFullscreen(!fbwindow().isFullscreen());
}
@ -500,6 +501,40 @@ void SetLayerCmd::real_execute() {
fbwindow().moveToLayer(m_layer);
}
namespace {
class SetTitleDialog: public TextDialog {
public:
SetTitleDialog(FluxboxWindow &win, const string &title):
TextDialog(win.screen(), title), window(win) {
setText(win.title());
}
private:
void exec(const std::string &text) {
window.winClient().setTitle(text);
}
FluxboxWindow &window;
};
} // end anonymous namespace
REGISTER_COMMAND(settitledialog, SetTitleDialogCmd, void);
void SetTitleDialogCmd::real_execute() {
_FB_USES_NLS;
SetTitleDialog *win = new SetTitleDialog(fbwindow(),
_FB_XTEXT(Windowmenu, SetTitle, "Set Title",
"Change the title of the window"));
win->show();
}
REGISTER_COMMAND_WITH_ARGS(settitle, SetTitleCmd, void);
void SetTitleCmd::real_execute() {
fbwindow().winClient().setTitle(title);
}
FbTk::Command<void> *SetAlphaCmd::parse(const string &command, const string &args,
bool trusted) {
typedef std::vector<string> StringTokens;

View file

@ -240,11 +240,27 @@ private:
class FullscreenCmd: public WindowHelperCmd{
public:
explicit FullscreenCmd();
explicit FullscreenCmd() { }
protected:
void real_execute();
};
class SetTitleDialogCmd: public WindowHelperCmd {
public:
explicit SetTitleDialogCmd() { }
protected:
void real_execute();
};
class SetTitleCmd: public WindowHelperCmd {
public:
explicit SetTitleCmd(std::string newtitle): title(newtitle) { }
protected:
void real_execute();
private:
std::string title;
};
class SetAlphaCmd: public WindowHelperCmd {
public:
SetAlphaCmd(int focus, bool rel, int unfocus, bool unrel);

View file

@ -124,6 +124,7 @@ fluxbox_SOURCES = AtomHandler.hh ArrowButton.hh ArrowButton.cc \
Xutil.hh Xutil.cc \
CurrentWindowCmd.hh CurrentWindowCmd.cc \
WorkspaceCmd.hh WorkspaceCmd.cc \
TextDialog.hh TextDialog.cc \
CommandDialog.hh CommandDialog.cc SendToMenu.hh SendToMenu.cc \
AlphaMenu.hh AlphaMenu.cc ObjectResource.hh \
CompareWindow.hh \

View file

@ -28,6 +28,7 @@
#include "fluxbox.hh"
#include "Window.hh"
#include "WindowCmd.hh"
#include "CurrentWindowCmd.hh"
#include "WindowMenuAccessor.hh"
#include "ClientMenu.hh"
@ -492,6 +493,12 @@ bool MenuCreator::createWindowMenuItem(const string &type,
_FB_XTEXT(Windowmenu, Stick,
"Stick", "Stick the window"):
label, res));
} else if (type == "settitledialog") {
RefCmd setname_cmd(new SetTitleDialogCmd());
menu.insert(label.empty() ?
_FB_XTEXT(Windowmenu, SetTitle,
"Set Title", "Change the title of the window"):
label, setname_cmd);
#ifdef HAVE_XRENDER
} else if (type == "alpha") {
if (FbTk::Transparent::haveComposite() ||

191
src/TextDialog.cc Normal file
View file

@ -0,0 +1,191 @@
// TextDialog.cc
// Copyright (c) 2008 Fluxbox Team (fluxgen at fluxbox dot org)
//
// 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,
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
// 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.
#include "TextDialog.hh"
#include "Screen.hh"
#include "FbWinFrameTheme.hh"
#include "fluxbox.hh"
#include "FbTk/ImageControl.hh"
#include "FbTk/EventManager.hh"
#include "FbTk/KeyUtil.hh"
#include <X11/keysym.h>
#include <X11/Xutil.h>
#include <memory>
#include <stdexcept>
using std::string;
/**
* This is an abstract class providing a text box dialog
*/
TextDialog::TextDialog(BScreen &screen,
const string &title) :
FbTk::FbWindow(screen.rootWindow().screenNumber(), 0, 0, 200, 1, ExposureMask),
m_textbox(*this, screen.focusedWinFrameTheme()->font(), ""),
m_label(*this, screen.focusedWinFrameTheme()->font(), title),
m_gc(m_textbox),
m_screen(screen),
m_move_x(0),
m_move_y(0),
m_pixmap(0){
init();
}
TextDialog::~TextDialog() {
FbTk::EventManager::instance()->remove(*this);
hide();
if (m_pixmap != 0)
m_screen.imageControl().removeImage(m_pixmap);
}
void TextDialog::setText(const string &text) {
m_textbox.setText(text);
}
void TextDialog::show() {
FbTk::FbWindow::show();
m_textbox.setInputFocus();
m_label.clear();
Fluxbox::instance()->setShowingDialog(true);
// resize to correct width, which should be the width of label text
// no need to truncate label text in this dialog
// but if label text size < 200 we set 200
if (m_label.textWidth() < 200)
return;
else {
resize(m_label.textWidth(), height());
updateSizes();
render();
}
}
void TextDialog::hide() {
FbTk::FbWindow::hide();
Fluxbox::instance()->setShowingDialog(false);
}
void TextDialog::exposeEvent(XExposeEvent &event) {
if (event.window == window())
clearArea(event.x, event.y, event.width, event.height);
}
void TextDialog::buttonPressEvent(XButtonEvent &event) {
m_textbox.setInputFocus();
m_move_x = event.x_root - x();
m_move_y = event.y_root - y();
}
void TextDialog::handleEvent(XEvent &event) {
if (event.type == ConfigureNotify && event.xconfigure.window != window()) {
moveResize(event.xconfigure.x, event.xconfigure.y,
event.xconfigure.width, event.xconfigure.height);
} else if (event.type == DestroyNotify)
delete this;
}
void TextDialog::motionNotifyEvent(XMotionEvent &event) {
int new_x = event.x_root - m_move_x;
int new_y = event.y_root - m_move_y;
move(new_x, new_y);
}
void TextDialog::keyPressEvent(XKeyEvent &event) {
unsigned int state = FbTk::KeyUtil::instance().isolateModifierMask(event.state);
if (state)
return;
KeySym ks;
char keychar;
XLookupString(&event, &keychar, 1, &ks, 0);
if (ks == XK_Return) {
exec(m_textbox.text());
delete this;
} else if (ks == XK_Escape)
delete this; // end this
else if (ks == XK_Tab) {
// try to expand a command
tabComplete();
}
}
void TextDialog::render() {
Pixmap tmp = m_pixmap;
if (!m_screen.focusedWinFrameTheme()->iconbarTheme().texture().usePixmap()) {
m_label.setBackgroundColor(m_screen.focusedWinFrameTheme()->iconbarTheme().texture().color());
m_pixmap = 0;
} else {
m_pixmap = m_screen.imageControl().renderImage(m_label.width(), m_label.height(),
m_screen.focusedWinFrameTheme()->iconbarTheme().texture());
m_label.setBackgroundPixmap(m_pixmap);
}
if (tmp)
m_screen.imageControl().removeImage(tmp);
}
void TextDialog::init() {
// setup label
// we listen to motion notify too
m_label.setEventMask(m_label.eventMask() | ButtonPressMask | ButtonMotionMask);
m_label.setGC(m_screen.focusedWinFrameTheme()->iconbarTheme().text().textGC());
m_label.show();
// setup text box
FbTk::Color white("white", m_textbox.screenNumber());
m_textbox.setBackgroundColor(white);
FbTk::Color black("black", m_textbox.screenNumber());
m_gc.setForeground(black);
m_textbox.setGC(m_gc.gc());
m_textbox.show();
// setup this window
setBorderWidth(1);
setBackgroundColor(white);
// move to center of the screen
move((m_screen.width() - width())/2, (m_screen.height() - height())/2);
updateSizes();
resize(width(), m_textbox.height() + m_label.height());
render();
// we need ConfigureNotify from children
FbTk::EventManager::instance()->addParent(*this, *this);
}
void TextDialog::updateSizes() {
m_label.moveResize(0, 0,
width(), m_textbox.font().height() + 2);
m_textbox.moveResize(2, m_label.height(),
width() - 4, m_textbox.font().height() + 2);
}

64
src/TextDialog.hh Normal file
View file

@ -0,0 +1,64 @@
// CommandDialog.hh
// Copyright (c) 2008 Fluxbox Team (fluxgen at fluxbox dot org)
//
// 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,
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
// 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.
#ifndef TEXTDIALOG_HH
#define TEXTDIALOG_HH
#include "FbTk/TextBox.hh"
#include "FbTk/TextButton.hh"
#include "FbTk/GContext.hh"
class BScreen;
class TextDialog: public FbTk::FbWindow, public FbTk::EventHandler {
public:
TextDialog(BScreen &screen, const std::string &title);
virtual ~TextDialog();
/// Sets the entry text.
void setText(const std::string &text);
void show();
void hide();
void exposeEvent(XExposeEvent &event);
void motionNotifyEvent(XMotionEvent &event);
void buttonPressEvent(XButtonEvent &event);
void handleEvent(XEvent &event);
void keyPressEvent(XKeyEvent &event);
protected:
virtual void exec(const std::string &text) = 0;
virtual void tabComplete() { }
void init();
void render();
void updateSizes();
FbTk::TextBox m_textbox; //< entry field
FbTk::TextButton m_label; //< text in the titlebar
FbTk::GContext m_gc;
BScreen &m_screen;
int m_move_x, m_move_y;
Pixmap m_pixmap;
};
#endif // TEXTDIALOG_HH