fluxbox/src/FbWinFrame.cc

1758 lines
53 KiB
C++
Raw Normal View History

2003-01-05 22:14:10 +00:00
// FbWinFrame.cc for Fluxbox Window Manager
2006-02-16 06:53:05 +00:00
// Copyright (c) 2003 - 2006 Henrik Kinnunen (fluxgen at fluxbox dot org)
2003-01-05 22:14:10 +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,
// 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.
2004-11-19 11:37:27 +00:00
// $Id$
2003-01-05 22:14:10 +00:00
#include "FbWinFrame.hh"
2003-08-19 16:15:32 +00:00
#include "FbTk/ImageControl.hh"
#include "FbTk/EventManager.hh"
#include "FbTk/App.hh"
#include "FbTk/SimpleCommand.hh"
2004-02-28 16:54:04 +00:00
#include "FbTk/Compose.hh"
#include "FbTk/Transparent.hh"
#include "CompareWindow.hh"
2003-07-10 11:36:21 +00:00
#include "FbWinFrameTheme.hh"
2006-03-20 11:31:24 +00:00
#include "Screen.hh"
#include "Container.hh"
2003-02-17 22:45:42 +00:00
#ifdef SHAPE
2003-07-10 11:36:21 +00:00
#include "Shape.hh"
2003-02-17 22:45:42 +00:00
#endif // SHAPE
2003-01-05 22:14:10 +00:00
2003-04-14 15:01:55 +00:00
#include <algorithm>
2003-09-11 13:35:37 +00:00
#include <X11/X.h>
2003-01-05 22:14:10 +00:00
#include <iostream>
using namespace std; // mem_fun
2006-03-20 11:31:24 +00:00
FbWinFrame::FbWinFrame(BScreen &screen, FbWinFrameTheme &theme, FbTk::ImageControl &imgctrl,
FbTk::XLayer &layer,
2003-12-18 18:03:23 +00:00
int x, int y,
2003-01-05 22:14:10 +00:00
unsigned int width, unsigned int height):
2006-03-20 11:31:24 +00:00
m_screen(screen),
2003-01-05 22:14:10 +00:00
m_theme(theme),
m_imagectrl(imgctrl),
2003-12-18 18:03:23 +00:00
m_window(theme.screenNum(), x, y, width, height, ButtonPressMask | ButtonReleaseMask |
2003-01-05 22:14:10 +00:00
ButtonMotionMask | EnterWindowMask, true),
2006-03-20 11:31:24 +00:00
m_layeritem(window(), layer),
2003-01-05 22:14:10 +00:00
m_titlebar(m_window, 0, 0, 100, 16,
ButtonPressMask | ButtonReleaseMask |
ButtonMotionMask | ExposureMask |
EnterWindowMask | LeaveWindowMask),
m_tab_container(m_titlebar),
2006-03-20 11:31:24 +00:00
m_label(m_titlebar, m_theme.font(), ""),
m_handle(m_window, 0, 0, 100, 5,
ButtonPressMask | ButtonReleaseMask |
ButtonMotionMask | ExposureMask |
EnterWindowMask | LeaveWindowMask),
m_grip_right(m_handle, 0, 0, 10, 4,
2003-01-05 22:14:10 +00:00
ButtonPressMask | ButtonReleaseMask |
ButtonMotionMask | ExposureMask |
EnterWindowMask | LeaveWindowMask),
m_grip_left(m_handle, 0, 0, 10, 4,
2003-01-05 22:14:10 +00:00
ButtonPressMask | ButtonReleaseMask |
ButtonMotionMask | ExposureMask |
EnterWindowMask | LeaveWindowMask),
m_clientarea(m_window, 0, 0, 100, 100,
ButtonPressMask | ButtonReleaseMask |
ButtonMotionMask | ExposureMask |
EnterWindowMask | LeaveWindowMask),
m_bevel(1),
m_use_titlebar(true),
2006-03-20 11:31:24 +00:00
m_use_tabs(true),
m_use_handle(true),
m_focused(false),
2003-05-01 13:19:36 +00:00
m_visible(false),
2003-02-15 01:54:54 +00:00
m_button_pm(0),
m_tabmode(screen.getDefaultInternalTabs()?INTERNAL:EXTERNAL),
m_need_render(true),
2003-07-10 11:36:21 +00:00
m_themelistener(*this),
m_shape(new Shape(m_window, theme.shapePlace())) {
m_theme.reconfigSig().attach(&m_themelistener);
2003-01-05 22:14:10 +00:00
init();
}
2003-04-14 15:01:55 +00:00
2003-01-05 22:14:10 +00:00
FbWinFrame::~FbWinFrame() {
removeEventHandler();
removeAllButtons();
}
bool FbWinFrame::setOnClickTitlebar(FbTk::RefCount<FbTk::Command> &ref, int mousebutton_num,
bool double_click, bool pressed) {
// find mousebutton_num
if (mousebutton_num < 1 || mousebutton_num > 5)
return false;
if (double_click)
m_commands[mousebutton_num - 1].double_click = ref;
else {
if (pressed)
m_commands[mousebutton_num - 1].click_pressed = ref;
else
m_commands[mousebutton_num - 1].click = ref;
}
return true;
}
2006-03-20 11:31:24 +00:00
bool FbWinFrame::setTabMode(TabMode tabmode) {
if (m_tabmode == tabmode)
return false;
bool ret = true;
// setting tabmode to notset forces it through when
// something is likely to change
if (tabmode == NOTSET)
tabmode = m_tabmode;
2006-03-22 12:23:17 +00:00
m_tabmode = tabmode;
2006-03-20 11:31:24 +00:00
// reparent tab container
if (tabmode == EXTERNAL) {
2006-03-22 12:23:17 +00:00
m_label.show();
2006-03-20 11:31:24 +00:00
m_tab_container.setBorderWidth(m_window.borderWidth());
m_tab_container.setBorderColor(theme().border().color());
m_tab_container.setEventMask(
ButtonPressMask | ButtonReleaseMask |
ButtonMotionMask | ExposureMask |
EnterWindowMask | LeaveWindowMask);
XGrabButton(m_tab_container.display(), Button1, AnyModifier,
m_tab_container.window(), True, ButtonPressMask,
GrabModeSync, GrabModeSync, None, None);
XUngrabButton(m_tab_container.display(), Button1, Mod1Mask|Mod2Mask|Mod3Mask, m_tab_container.window());
2006-03-26 12:32:15 +00:00
alignTabs();
2006-03-20 11:31:24 +00:00
// TODO: tab position
if (m_use_tabs && m_visible)
m_tab_container.show();
else {
ret = false;
m_tab_container.hide();
}
} else {
2006-03-26 12:32:15 +00:00
m_tab_container.setUpdateLock(true);
2006-03-22 12:23:17 +00:00
m_tab_container.setAlignment(Container::RELATIVE);
m_tab_container.setOrientation(FbTk::ROT0);
2006-03-20 11:31:24 +00:00
if (m_tab_container.parent()->window() == m_screen.rootWindow().window()) {
m_layeritem.removeWindow(m_tab_container);
m_tab_container.reparent(m_titlebar, m_label.x(), m_label.y());
2006-03-22 12:23:17 +00:00
m_tab_container.resize(m_label.width(), m_label.height());
2006-03-20 11:31:24 +00:00
m_tab_container.raise();
}
m_tab_container.setBorderWidth(0);
m_tab_container.setMaxTotalSize(0);
m_tab_container.setUpdateLock(false);
2006-03-20 11:31:24 +00:00
m_tab_container.setMaxSizePerClient(0);
renderTabContainer();
applyTabContainer();
m_tab_container.clear();
m_tab_container.raise();
m_tab_container.show();
2006-03-20 11:31:24 +00:00
if (!m_use_tabs)
ret = false;
2006-03-22 12:23:17 +00:00
m_label.hide();
2006-03-20 11:31:24 +00:00
// reconfigure();
}
return true;
}
2003-01-05 22:14:10 +00:00
void FbWinFrame::hide() {
m_window.hide();
2006-03-20 11:31:24 +00:00
if (m_tabmode == EXTERNAL && m_use_tabs)
m_tab_container.hide();
2003-05-01 13:19:36 +00:00
m_visible = false;
2003-01-05 22:14:10 +00:00
}
void FbWinFrame::show() {
2003-05-01 13:19:36 +00:00
m_visible = true;
if (m_need_render) {
renderAll();
applyAll();
clearAll();
}
2006-03-20 11:31:24 +00:00
if (m_tabmode == EXTERNAL && m_use_tabs)
m_tab_container.show();
2003-01-05 22:14:10 +00:00
m_window.showSubwindows();
m_window.show();
}
/**
Toggle shade state, and resize window
*/
void FbWinFrame::shade() {
2003-02-20 23:21:23 +00:00
if (!m_use_titlebar)
return;
2003-04-03 22:37:43 +00:00
// toggle shade
m_shaded = !m_shaded;
if (m_shaded) { // i.e. should be shaded now
2003-01-05 22:14:10 +00:00
m_width_before_shade = m_window.width();
m_height_before_shade = m_window.height();
2003-02-23 21:32:37 +00:00
m_window.resize(m_window.width(), m_titlebar.height());
2006-03-24 15:19:02 +00:00
alignTabs();
2003-04-03 22:37:43 +00:00
} else { // should be unshaded
2003-01-05 22:14:10 +00:00
m_window.resize(m_width_before_shade, m_height_before_shade);
2003-04-03 22:37:43 +00:00
reconfigure();
2003-01-05 22:14:10 +00:00
}
}
void FbWinFrame::move(int x, int y, int win_gravity) {
moveResize(x, y, 0, 0, true, false, win_gravity);
}
2003-08-04 12:47:36 +00:00
void FbWinFrame::resize(unsigned int width, unsigned int height, int win_gravity) {
moveResize(0, 0, width, height, false, true, win_gravity);
}
// need an atomic moveresize where possible
void FbWinFrame::moveResizeForClient(int x, int y, unsigned int width, unsigned int height, bool move, bool resize, int win_gravity) {
// total height for frame
2003-08-04 12:47:36 +00:00
unsigned int total_height = height;
2003-08-04 12:47:36 +00:00
if (resize) {
// having a titlebar = 1 extra border + titlebar height
if (m_use_titlebar)
total_height += m_titlebar.height() + m_titlebar.borderWidth();
// having a handle = 1 extra border + handle height
if (m_use_handle)
total_height += m_handle.height() + m_handle.borderWidth();
}
moveResize(x, y, width, total_height, move, resize, win_gravity);
}
void FbWinFrame::resizeForClient(unsigned int width, unsigned int height, int win_gravity) {
moveResizeForClient(0, 0, width, height, false, true, win_gravity);
2003-01-05 22:14:10 +00:00
}
void FbWinFrame::moveResize(int x, int y, unsigned int width, unsigned int height, bool move, bool resize, int win_gravity) {
if(win_gravity!=ForgetGravity) {
gravityTranslate(x, y, width + m_window.borderWidth()*2, height + m_window.borderWidth()*2, win_gravity, false);
}
if (move && x == window().x() && y == window().y())
move = false;
if (resize && width == FbWinFrame::width() && height == FbWinFrame::height())
resize = false;
if (!move && !resize)
return;
if (resize && m_shaded) {
// update unshaded size if we're in shaded state and just resize width
2003-01-05 22:14:10 +00:00
m_width_before_shade = width;
m_height_before_shade = height;
height = m_window.height();
}
if (move && resize) {
m_window.moveResize(x, y, width, height);
notifyMoved(false); // will reconfigure
} else if (move) {
m_window.move(x, y);
// this stuff will be caught by reconfigure if resized
notifyMoved(true);
2003-01-05 22:14:10 +00:00
} else {
m_window.resize(width, height);
}
if (move || resize && m_screen.getTabPlacement() != TOPLEFT)
2006-03-20 11:31:24 +00:00
alignTabs();
if (resize) {
if (m_tabmode == EXTERNAL) {
switch(m_screen.getTabPlacement()) {
case LEFTTOP:
case RIGHTTOP:
case LEFTBOTTOM:
case RIGHTBOTTOM:
m_tab_container.setMaxTotalSize(height);
break;
default:
m_tab_container.setMaxTotalSize(width);
break;
}
}
reconfigure();
2006-03-20 11:31:24 +00:00
}
}
void FbWinFrame::quietMoveResize(int x, int y,
unsigned int width, unsigned int height) {
m_window.moveResize(x, y, width, height);
if (m_tabmode == EXTERNAL) {
switch(m_screen.getTabPlacement()) {
case LEFTTOP:
case RIGHTTOP:
case LEFTBOTTOM:
case RIGHTBOTTOM:
m_tab_container.setMaxTotalSize(height);
break;
default:
m_tab_container.setMaxTotalSize(width);
break;
}
2006-03-20 11:31:24 +00:00
alignTabs();
}
}
void FbWinFrame::alignTabs() {
2006-03-22 12:23:17 +00:00
if (m_tabmode != EXTERNAL)
return;
2006-03-26 12:32:15 +00:00
FbTk::Orientation orig_orient = m_tab_container.orientation();
unsigned int orig_tabwidth = m_tab_container.maxWidthPerClient();
if (orig_tabwidth != m_screen.getTabWidth())
m_tab_container.setMaxSizePerClient(m_screen.getTabWidth());
2006-03-22 12:23:17 +00:00
int tabx = 0, taby = 0;
switch (m_screen.getTabPlacement()) {
2006-03-22 12:23:17 +00:00
case TOPLEFT:
2006-03-26 12:32:15 +00:00
if (orig_orient != FbTk::ROT0) m_tab_container.hide();
m_tab_container.setOrientation(FbTk::ROT0);
2006-03-26 12:32:15 +00:00
m_tab_container.setAlignment(Container::LEFT);
2006-03-22 12:23:17 +00:00
tabx = x();
taby = y() - yOffset();
break;
case TOPRIGHT:
2006-03-26 12:32:15 +00:00
if (orig_orient != FbTk::ROT0) m_tab_container.hide();
m_tab_container.setOrientation(FbTk::ROT0);
2006-03-26 12:32:15 +00:00
m_tab_container.setAlignment(Container::RIGHT);
2006-03-22 12:23:17 +00:00
tabx = x() + width() - m_tab_container.width();
taby = y() - yOffset();
break;
case LEFTTOP:
2006-03-26 12:32:15 +00:00
if (orig_orient != FbTk::ROT270) m_tab_container.hide();
m_tab_container.setOrientation(FbTk::ROT270);
2006-03-26 12:32:15 +00:00
m_tab_container.setAlignment(Container::RIGHT);
tabx = x() - xOffset();
taby = y();
break;
case LEFTBOTTOM:
2006-03-26 12:32:15 +00:00
if (orig_orient != FbTk::ROT270) m_tab_container.hide();
m_tab_container.setOrientation(FbTk::ROT270);
2006-03-26 12:32:15 +00:00
m_tab_container.setAlignment(Container::LEFT);
tabx = x() - xOffset();
taby = y() + height() - m_tab_container.height();
break;
case RIGHTTOP:
2006-03-26 12:32:15 +00:00
if (orig_orient != FbTk::ROT90) m_tab_container.hide();
m_tab_container.setOrientation(FbTk::ROT90);
2006-03-26 12:32:15 +00:00
m_tab_container.setAlignment(Container::LEFT);
tabx = x() + width() + m_window.borderWidth();
taby = y();
break;
case RIGHTBOTTOM:
2006-03-26 12:32:15 +00:00
if (orig_orient != FbTk::ROT90) m_tab_container.hide();
m_tab_container.setOrientation(FbTk::ROT90);
2006-03-26 12:32:15 +00:00
m_tab_container.setAlignment(Container::RIGHT);
tabx = x() + width() + m_window.borderWidth();
taby = y() + height() - m_tab_container.height();
break;
2006-03-22 12:23:17 +00:00
case BOTTOMLEFT:
2006-03-26 12:32:15 +00:00
if (orig_orient != FbTk::ROT0) m_tab_container.hide();
m_tab_container.setOrientation(FbTk::ROT0);
2006-03-26 12:32:15 +00:00
m_tab_container.setAlignment(Container::LEFT);
2006-03-22 12:23:17 +00:00
tabx = x();
taby = y() + height() + m_window.borderWidth();
break;
case BOTTOMRIGHT:
2006-03-26 12:32:15 +00:00
if (orig_orient != FbTk::ROT0) m_tab_container.hide();
m_tab_container.setOrientation(FbTk::ROT0);
2006-03-26 12:32:15 +00:00
m_tab_container.setAlignment(Container::RIGHT);
2006-03-22 12:23:17 +00:00
tabx = x() + width() - m_tab_container.width();
taby = y() + height() + m_window.borderWidth();
break;
}
2006-03-26 12:32:15 +00:00
unsigned int w = m_window.width(), h = m_window.height();
translateSize(m_tab_container.orientation(), w, h);
m_tab_container.setMaxTotalSize(w);
if (m_tab_container.orientation() != orig_orient ||
m_tab_container.maxWidthPerClient() != orig_tabwidth) {
renderTabContainer();
2006-03-26 12:32:15 +00:00
if (m_visible && m_use_tabs) {
applyTabContainer();
m_tab_container.clear();
m_tab_container.show();
}
}
2006-03-26 12:32:15 +00:00
if (m_tab_container.parent()->window() != m_screen.rootWindow().window()) {
m_tab_container.reparent(m_screen.rootWindow(), tabx, taby);
m_layeritem.addWindow(m_tab_container);
} else {
m_tab_container.move(tabx, taby);
}
2003-01-05 22:14:10 +00:00
}
void FbWinFrame::notifyMoved(bool clear) {
// not important if no alpha...
unsigned char alpha = (m_focused?theme().focusedAlpha():theme().unfocusedAlpha());
if (alpha == 255)
return;
2006-03-20 11:31:24 +00:00
if (m_tabmode == EXTERNAL && m_use_tabs || m_use_titlebar) {
m_tab_container.parentMoved();
m_tab_container.for_each(mem_fun(&FbTk::Button::parentMoved));
}
if (m_use_titlebar) {
if (m_tabmode != INTERNAL)
2006-03-20 11:31:24 +00:00
m_label.parentMoved();
m_titlebar.parentMoved();
for_each(m_buttons_left.begin(),
m_buttons_left.end(),
mem_fun(&FbTk::Button::parentMoved));
for_each(m_buttons_right.begin(),
m_buttons_right.end(),
mem_fun(&FbTk::Button::parentMoved));
}
if (m_use_handle) {
m_handle.parentMoved();
m_grip_left.parentMoved();
m_grip_right.parentMoved();
}
if (clear && (m_use_handle || m_use_titlebar)) {
clearAll();
2006-03-20 11:31:24 +00:00
} else if (clear && m_tabmode == EXTERNAL && m_use_tabs)
m_tab_container.clear();
}
void FbWinFrame::clearAll() {
if (m_use_titlebar) {
redrawTitlebar();
for_each(m_buttons_left.begin(),
m_buttons_left.end(),
mem_fun(&FbTk::Button::clear));
for_each(m_buttons_right.begin(),
m_buttons_right.end(),
mem_fun(&FbTk::Button::clear));
2006-03-20 11:31:24 +00:00
} else if (m_tabmode == EXTERNAL && m_use_tabs)
m_tab_container.clear();
if (m_use_handle) {
m_handle.clear();
m_grip_left.clear();
m_grip_right.clear();
}
}
2003-01-05 22:14:10 +00:00
void FbWinFrame::setFocus(bool newvalue) {
2003-09-14 10:32:31 +00:00
if (m_focused == newvalue)
2003-01-05 22:14:10 +00:00
return;
m_focused = newvalue;
if (FbTk::Transparent::haveRender() && theme().focusedAlpha() != theme().unfocusedAlpha()) {
unsigned char alpha = (m_focused?theme().focusedAlpha():theme().unfocusedAlpha());
if (FbTk::Transparent::haveComposite()) {
m_window.setOpaque(alpha);
} else {
m_tab_container.setAlpha(alpha);
}
}
2003-09-14 10:32:31 +00:00
if (currentLabel()) {
if (newvalue) // focused
applyFocusLabel(*m_current_label);
2003-09-14 10:32:31 +00:00
else // unfocused
applyActiveLabel(*m_current_label);
2003-09-12 22:49:14 +00:00
}
applyTitlebar();
applyHandles();
2006-03-20 11:31:24 +00:00
applyTabContainer();
clearAll();
2003-01-05 22:14:10 +00:00
}
void FbWinFrame::setDoubleClickTime(unsigned int time) {
m_double_click_time = time;
}
2003-01-05 22:14:10 +00:00
void FbWinFrame::addLeftButton(FbTk::Button *btn) {
if (btn == 0) // valid button?
return;
applyButton(*btn); // setup theme and other stuff
2003-09-14 10:32:31 +00:00
2003-01-05 22:14:10 +00:00
m_buttons_left.push_back(btn);
}
void FbWinFrame::addRightButton(FbTk::Button *btn) {
if (btn == 0) // valid button?
return;
applyButton(*btn); // setup theme and other stuff
2003-01-05 22:14:10 +00:00
m_buttons_right.push_back(btn);
}
void FbWinFrame::removeAllButtons() {
// destroy left side
while (!m_buttons_left.empty()) {
delete m_buttons_left.back();
m_buttons_left.pop_back();
}
// destroy right side
while (!m_buttons_right.empty()) {
delete m_buttons_right.back();
m_buttons_right.pop_back();
}
2003-04-14 15:01:55 +00:00
}
FbWinFrame::ButtonId FbWinFrame::createTab(const std::string &title, FbTk::Command *command,
int tabs_padding) {
FbTk::TextButton *button = new FbTk::TextButton(m_tab_container,
theme().font(),
title);
button->show();
button->setEventMask(ExposureMask | ButtonPressMask |
ButtonReleaseMask | ButtonMotionMask |
EnterWindowMask);
FbTk::EventManager::instance()->add(*button, button->window());
2003-04-14 15:01:55 +00:00
FbTk::RefCount<FbTk::Command> refcmd(command);
button->setOnClick(refcmd);
button->setTextPadding(tabs_padding);
button->setJustify(theme().justify());
button->setBorderColor(theme().border().color());
button->setBorderWidth(m_window.borderWidth());
m_tab_container.insertItem(button);
2003-12-09 08:48:08 +00:00
if (currentLabel() == 0)
setLabelButtonFocus(*button);
return button;
2003-04-14 15:01:55 +00:00
}
void FbWinFrame::removeTab(ButtonId btn) {
if (btn == m_current_label)
2004-03-21 09:00:25 +00:00
m_current_label = 0;
if (m_tab_container.removeItem(btn))
delete btn;
2003-01-05 22:14:10 +00:00
}
void FbWinFrame::moveLabelButtonLeft(FbTk::TextButton &btn) {
m_tab_container.moveItem(&btn, -1);
}
void FbWinFrame::moveLabelButtonRight(FbTk::TextButton &btn) {
m_tab_container.moveItem(&btn, +1);
}
void FbWinFrame::moveLabelButtonTo(FbTk::TextButton &btn, int x, int y) {
m_tab_container.moveItemTo(&btn, x, y);
}
void FbWinFrame::moveLabelButtonLeftOf(FbTk::TextButton &btn, const FbTk::TextButton &dest) {
int dest_pos = m_tab_container.find(&dest);
int cur_pos = m_tab_container.find(&btn);
if (dest_pos < 0 || cur_pos < 0)
2005-05-03 09:25:46 +00:00
return;
int movement=dest_pos - cur_pos;
if(movement>0)
movement-=1;
// else
// movement-=1;
2005-05-03 09:25:46 +00:00
m_tab_container.moveItem(&btn, movement);
}
void FbWinFrame::moveLabelButtonRightOf(FbTk::TextButton &btn, const FbTk::TextButton &dest) {
int dest_pos = m_tab_container.find(&dest);
int cur_pos = m_tab_container.find(&btn);
if (dest_pos < 0 || cur_pos < 0 )
2005-05-03 09:25:46 +00:00
return;
int movement=dest_pos - cur_pos;
if(movement<0)
movement+=1;
2005-05-03 09:25:46 +00:00
m_tab_container.moveItem(&btn, movement);
}
2003-08-19 16:15:32 +00:00
void FbWinFrame::setLabelButtonFocus(FbTk::TextButton &btn) {
if (&btn == currentLabel() || btn.parent() != &m_tab_container)
2003-04-16 12:27:49 +00:00
return;
// render label buttons
2003-09-12 22:49:14 +00:00
if (currentLabel() != 0)
applyUnfocusLabel(*m_current_label);
2005-05-03 09:25:46 +00:00
m_current_label = &btn; // current focused button
2006-03-20 11:31:24 +00:00
m_label.setText(btn.text());
2003-12-09 08:48:08 +00:00
if (m_focused)
applyFocusLabel(*m_current_label);
2003-12-09 08:48:08 +00:00
else
applyActiveLabel(*m_current_label);
2003-04-16 12:27:49 +00:00
}
2003-04-14 15:01:55 +00:00
void FbWinFrame::setClientWindow(FbTk::FbWindow &win) {
2003-01-05 22:14:10 +00:00
win.setBorderWidth(0);
2005-05-03 09:25:46 +00:00
XChangeSaveSet(win.display(), win.window(), SetModeInsert);
m_window.setEventMask(NoEventMask);
// we need to mask this so we don't get unmap event
win.setEventMask(NoEventMask);
win.reparent(m_window, 0, clientArea().y());
// remask window so we get events
win.setEventMask(PropertyChangeMask | StructureNotifyMask |
FocusChangeMask);
m_window.setEventMask(ButtonPressMask | ButtonReleaseMask |
ButtonMotionMask | EnterWindowMask | SubstructureRedirectMask);
2003-01-05 22:14:10 +00:00
2005-05-03 09:25:46 +00:00
XFlush(win.display());
2003-01-05 22:14:10 +00:00
XSetWindowAttributes attrib_set;
2003-01-05 22:14:10 +00:00
attrib_set.event_mask = PropertyChangeMask | StructureNotifyMask | FocusChangeMask;
attrib_set.do_not_propagate_mask = ButtonPressMask | ButtonReleaseMask |
ButtonMotionMask;
2003-01-05 22:14:10 +00:00
2005-05-03 09:25:46 +00:00
XChangeWindowAttributes(win.display(), win.window(), CWEventMask|CWDontPropagate, &attrib_set);
2003-01-05 22:14:10 +00:00
m_clientarea.raise();
2006-03-20 11:31:24 +00:00
win.show();
win.raise();
m_window.showSubwindows();
2003-01-05 22:14:10 +00:00
}
2006-03-20 11:31:24 +00:00
bool FbWinFrame::hideTabs() {
if (m_tabmode == INTERNAL || !m_use_tabs) {
m_use_tabs = false;
return false;
}
m_use_tabs = false;
m_tab_container.hide();
return true;
}
bool FbWinFrame::showTabs() {
if (m_tabmode == INTERNAL || m_use_tabs) {
m_use_tabs = true;
return false; // nothing changed
}
m_use_tabs = true;
if (m_visible)
m_tab_container.show();
return true;
}
bool FbWinFrame::hideTitlebar() {
2003-02-20 23:21:23 +00:00
if (!m_use_titlebar)
return false;
2003-02-20 23:21:23 +00:00
2003-01-05 22:14:10 +00:00
m_titlebar.hide();
m_use_titlebar = false;
if (static_cast<signed int>(m_window.height() - m_titlebar.height() -
m_titlebar.borderWidth()) <= 0) {
m_window.resize(m_window.width(), 1);
} else {
// only take away one borderwidth (as the other border is still the "top" border)
m_window.resize(m_window.width(), m_window.height() - m_titlebar.height() -
m_titlebar.borderWidth());
}
return true;
2003-01-05 22:14:10 +00:00
}
bool FbWinFrame::showTitlebar() {
2003-02-20 23:21:23 +00:00
if (m_use_titlebar)
return false;
2003-02-20 23:21:23 +00:00
2003-01-05 22:14:10 +00:00
m_titlebar.show();
m_use_titlebar = true;
// only add one borderwidth (as the other border is still the "top" border)
m_window.resize(m_window.width(), m_window.height() + m_titlebar.height() +
m_titlebar.borderWidth());
2006-03-20 11:31:24 +00:00
return true;
2003-01-05 22:14:10 +00:00
}
bool FbWinFrame::hideHandle() {
if (!m_use_handle)
return false;
2003-01-05 22:14:10 +00:00
m_handle.hide();
m_grip_left.hide();
m_grip_right.hide();
m_use_handle = false;
if (static_cast<signed int>(m_window.height() - m_handle.height() -
2004-01-23 11:04:05 +00:00
m_handle.borderWidth()) <= 0) {
m_window.resize(m_window.width(), 1);
} else {
// only take away one borderwidth (as the other border is still the "top" border)
m_window.resize(m_window.width(), m_window.height() - m_handle.height() -
m_handle.borderWidth());
}
return true;
2003-01-05 22:14:10 +00:00
}
bool FbWinFrame::showHandle() {
if (m_use_handle || theme().handleWidth() == 0)
return false;
// weren't previously rendered...
renderHandles();
m_use_handle = true;
2003-01-05 22:14:10 +00:00
m_handle.show();
m_handle.showSubwindows(); // shows grips
m_window.resize(m_window.width(), m_window.height() + m_handle.height() +
m_handle.borderWidth());
return true;
}
bool FbWinFrame::hideAllDecorations() {
bool changed = false;
changed |= hideHandle();
changed |= hideTitlebar();
// resize done by hide*
reconfigure();
return changed;
}
bool FbWinFrame::showAllDecorations() {
bool changed = false;
if (!m_use_handle)
changed |= showHandle();
if (!m_use_titlebar)
changed |= showTitlebar();
// resize shouldn't be necessary
2003-02-22 18:31:00 +00:00
reconfigure();
return changed;
2003-01-05 22:14:10 +00:00
}
/**
Set new event handler for the frame's windows
*/
void FbWinFrame::setEventHandler(FbTk::EventHandler &evh) {
FbTk::EventManager &evm = *FbTk::EventManager::instance();
evm.add(evh, m_tab_container);
2006-03-20 11:31:24 +00:00
evm.add(evh, m_label);
2003-01-05 22:14:10 +00:00
evm.add(evh, m_titlebar);
evm.add(evh, m_handle);
evm.add(evh, m_grip_right);
evm.add(evh, m_grip_left);
evm.add(evh, m_window);
evm.add(evh, m_clientarea);
}
/**
remove event handler from windows
*/
void FbWinFrame::removeEventHandler() {
FbTk::EventManager &evm = *FbTk::EventManager::instance();
evm.remove(m_tab_container);
2006-03-20 11:31:24 +00:00
evm.remove(m_label);
2003-01-05 22:14:10 +00:00
evm.remove(m_titlebar);
evm.remove(m_handle);
evm.remove(m_grip_right);
evm.remove(m_grip_left);
evm.remove(m_window);
evm.remove(m_clientarea);
}
void FbWinFrame::buttonPressEvent(XButtonEvent &event) {
2003-04-14 15:01:55 +00:00
// we can ignore which window the event was generated for
2006-03-20 11:31:24 +00:00
if (event.window == m_label.window() && m_current_label)
event.window = m_current_label->window();
m_tab_container.tryButtonPressEvent(event);
if (event.window == m_grip_right.window() ||
event.window == m_grip_left.window() ||
event.window == m_clientarea.window() ||
event.window == m_window.window())
return;
2003-08-04 12:47:36 +00:00
// we handle only buttons 0 to 5
if (event.button > 5 || event.button < 1)
return;
2003-01-09 18:03:33 +00:00
if (*m_commands[event.button - 1].click_pressed)
m_commands[event.button - 1].click_pressed->execute();
}
void FbWinFrame::buttonReleaseEvent(XButtonEvent &event) {
2003-04-14 15:01:55 +00:00
// we can ignore which window the event was generated for
2006-03-20 11:31:24 +00:00
if (event.window == m_label.window() && m_current_label)
event.window = m_current_label->window();
2003-04-14 15:01:55 +00:00
// we continue even if a button got the event
m_tab_container.tryButtonReleaseEvent(event);
2003-08-24 11:19:45 +00:00
if (event.window == m_grip_right.window() ||
event.window == m_grip_left.window() ||
event.window == m_clientarea.window() ||
event.window == m_handle.window() ||
event.window == m_window.window())
return;
if (event.button < 1 || event.button > 5)
return;
static Time last_release_time = 0;
bool double_click = (event.time - last_release_time <= m_double_click_time);
last_release_time = event.time;
int real_button = event.button - 1;
if (double_click && *m_commands[real_button].double_click)
m_commands[real_button].double_click->execute();
else if (*m_commands[real_button].click)
m_commands[real_button].click->execute();
2003-01-05 22:14:10 +00:00
}
void FbWinFrame::exposeEvent(XExposeEvent &event) {
2004-01-10 00:37:35 +00:00
if (m_titlebar == event.window) {
m_titlebar.clearArea(event.x, event.y, event.width, event.height);
} else if (m_tab_container == event.window) {
m_tab_container.clearArea(event.x, event.y, event.width, event.height);
2006-03-20 11:31:24 +00:00
} else if (m_label == event.window) {
m_label.clearArea(event.x, event.y, event.width, event.height);
2003-09-12 22:49:14 +00:00
} else if (m_handle == event.window) {
2003-08-04 12:47:36 +00:00
m_handle.clearArea(event.x, event.y, event.width, event.height);
} else if (m_grip_left == event.window) {
m_grip_left.clearArea(event.x, event.y, event.width, event.height);
} else if (m_grip_right == event.window) {
m_grip_right.clearArea(event.x, event.y, event.width, event.height);
} else {
if (m_tab_container.tryExposeEvent(event))
return;
2003-08-24 11:19:45 +00:00
// create compare function
// that we should use with find_if
FbTk::CompareEqual_base<FbTk::FbWindow, Window> compare(&FbTk::FbWindow::window,
event.window);
2003-08-24 11:19:45 +00:00
ButtonList::iterator it = find_if(m_buttons_left.begin(),
m_buttons_left.end(),
compare);
if (it != m_buttons_left.end()) {
(*it)->exposeEvent(event);
return;
2003-08-04 12:47:36 +00:00
}
2003-08-24 11:19:45 +00:00
it = find_if(m_buttons_right.begin(),
m_buttons_right.end(),
compare);
2003-08-04 12:47:36 +00:00
2003-08-24 11:19:45 +00:00
if (it != m_buttons_right.end())
(*it)->exposeEvent(event);
}
2003-09-12 22:49:14 +00:00
2003-01-05 22:14:10 +00:00
}
void FbWinFrame::handleEvent(XEvent &event) {
2003-08-23 15:46:06 +00:00
if (event.type == ConfigureNotify && event.xconfigure.window == window().window())
2003-01-05 22:14:10 +00:00
configureNotifyEvent(event.xconfigure);
}
void FbWinFrame::configureNotifyEvent(XConfigureEvent &event) {
resize(event.width, event.height);
}
void FbWinFrame::reconfigure() {
if (m_tab_container.empty())
2003-09-12 22:49:14 +00:00
return;
2003-01-09 18:03:33 +00:00
2003-09-12 23:38:50 +00:00
m_bevel = theme().bevelWidth();
// reconfigure can't set borderwidth, as it doesn't know
// if it's meant to be borderless or not
unsigned int orig_handle_h = handle().height();
if (m_use_handle && orig_handle_h != theme().handleWidth())
m_window.resize(m_window.width(), m_window.height() -
orig_handle_h + theme().handleWidth());
2003-09-12 23:38:50 +00:00
handle().resize(handle().width(),
theme().handleWidth());
gripLeft().resize(buttonHeight(),
theme().handleWidth());
gripRight().resize(gripLeft().width(),
gripLeft().height());
2003-01-05 22:14:10 +00:00
// align titlebar and render it
if (m_use_titlebar) {
reconfigureTitlebar();
m_titlebar.raise();
} else
m_titlebar.lower();
if (m_tabmode == EXTERNAL) {
unsigned int neww, newh;
switch (m_screen.getTabPlacement()) {
case TOPLEFT:
case TOPRIGHT:
case BOTTOMLEFT:
case BOTTOMRIGHT:
neww = m_tab_container.width();
newh = buttonHeight();
break;
default:
neww = buttonHeight();
newh = m_tab_container.height();
break;
}
m_tab_container.resize(neww, newh);
alignTabs();
}
2003-02-20 23:21:23 +00:00
2003-04-03 22:37:43 +00:00
// leave client+grips alone if we're shaded (it'll get fixed when we unshade)
if (!m_shaded) {
int client_top = 0;
int client_height = m_window.height();
if (m_use_titlebar) {
// only one borderwidth as titlebar is really at -borderwidth
int titlebar_height = m_titlebar.height() + m_titlebar.borderWidth();
client_top += titlebar_height;
client_height -= titlebar_height;
}
// align handle and grips
const int grip_height = m_handle.height();
const int grip_width = 20; //TODO
const int handle_bw = static_cast<signed>(m_handle.borderWidth());
int ypos = m_window.height();
// if the handle isn't on, it's actually below the window
if (m_use_handle)
ypos -= grip_height + handle_bw;
// we do handle settings whether on or not so that if they get toggled
// then things are ok...
m_handle.moveResize(-handle_bw, ypos,
m_window.width(), grip_height);
m_grip_left.moveResize(-handle_bw, -handle_bw,
grip_width, grip_height);
m_grip_right.moveResize(m_handle.width() - grip_width - handle_bw, -handle_bw,
grip_width, grip_height);
if (m_use_handle) {
m_handle.raise();
client_height -= m_handle.height() + m_handle.borderWidth();
} else {
m_handle.lower();
2003-04-16 10:56:37 +00:00
}
m_clientarea.moveResize(0, client_top,
m_window.width(), client_height);
}
2003-01-05 22:14:10 +00:00
// render the theme
if (isVisible()) {
renderAll();
applyAll();
clearAll();
} else {
m_need_render = true;
}
2003-07-10 11:36:21 +00:00
if (m_shape.get() && theme().shapePlace() == Shape::NONE || m_disable_shape)
2003-07-10 11:36:21 +00:00
m_shape.reset(0);
else if (m_shape.get() == 0 && theme().shapePlace() != Shape::NONE)
m_shape.reset(new Shape(window(), theme().shapePlace()));
else if (m_shape.get())
m_shape->setPlaces(theme().shapePlace());
if (m_shape.get())
m_shape->update();
2003-05-01 13:19:36 +00:00
// titlebar stuff rendered already by reconftitlebar
2003-01-05 22:14:10 +00:00
}
void FbWinFrame::setUseShape(bool value) {
m_disable_shape = !value;
if (m_shape.get() && m_disable_shape)
m_shape.reset(0);
else if (m_shape.get() == 0 && !m_disable_shape)
m_shape.reset(new Shape(window(), theme().shapePlace()));
}
2003-01-05 22:14:10 +00:00
unsigned int FbWinFrame::buttonHeight() const {
return m_titlebar.height() - m_bevel*2;
}
//--------------------- private area
/**
aligns and redraws title
*/
void FbWinFrame::redrawTitlebar() {
if (!m_use_titlebar || m_tab_container.empty())
2003-04-14 15:01:55 +00:00
return;
if (isVisible()) {
m_tab_container.clear();
2006-03-20 11:31:24 +00:00
m_label.clear();
2003-10-09 16:48:09 +00:00
m_titlebar.clear();
2003-04-14 15:01:55 +00:00
}
2003-01-05 22:14:10 +00:00
}
/**
Align buttons with title text window
*/
void FbWinFrame::reconfigureTitlebar() {
2003-02-20 23:21:23 +00:00
if (!m_use_titlebar)
return;
int orig_height = m_titlebar.height();
2003-01-05 22:14:10 +00:00
// resize titlebar to window size with font height
2003-08-22 15:20:32 +00:00
int title_height = m_theme.font().height() == 0 ? 16 :
m_theme.font().height() + m_bevel*2 + 2;
if (m_theme.titleHeight() != 0)
title_height = m_theme.titleHeight();
// if the titlebar grows in size, make sure the whole window does too
if (orig_height != title_height)
m_window.resize(m_window.width(), m_window.height()-orig_height+title_height);
2003-02-17 22:45:42 +00:00
m_titlebar.moveResize(-m_titlebar.borderWidth(), -m_titlebar.borderWidth(),
2003-08-22 15:20:32 +00:00
m_window.width(), title_height);
2003-01-05 22:14:10 +00:00
// draw left buttons first
unsigned int next_x = m_bevel;
unsigned int button_size = buttonHeight();
m_button_size = button_size;
for (size_t i=0; i < m_buttons_left.size(); i++, next_x += button_size + m_bevel) {
m_buttons_left[i]->moveResize(next_x, m_bevel,
button_size, button_size);
}
2003-04-14 15:01:55 +00:00
2003-01-05 22:14:10 +00:00
next_x += m_bevel;
2003-01-05 22:14:10 +00:00
// space left on titlebar between left and right buttons
2006-03-20 11:31:24 +00:00
int space_left = m_titlebar.width() - next_x;
2004-01-21 14:14:40 +00:00
if (!m_buttons_right.empty())
2003-02-17 22:45:42 +00:00
space_left -= m_buttons_right.size() * (button_size + m_bevel);
2003-01-05 22:14:10 +00:00
space_left -= m_bevel;
2006-03-20 11:31:24 +00:00
if (space_left <= 0)
space_left = 1;
m_label.moveResize(next_x, m_bevel, space_left, button_size);
if (m_tabmode == INTERNAL)
m_tab_container.moveResize(next_x, m_bevel,
space_left, button_size);
else {
if (m_use_tabs) {
if (m_tab_container.orientation() == FbTk::ROT0) {
m_tab_container.resize(m_tab_container.width(), button_size);
} else {
m_tab_container.resize(button_size, m_tab_container.height());
}
}
}
2006-03-20 11:31:24 +00:00
next_x += m_label.width() + m_bevel;
2003-01-05 22:14:10 +00:00
// finaly set new buttons to the right
for (size_t i=0; i < m_buttons_right.size();
++i, next_x += button_size + m_bevel) {
m_buttons_right[i]->moveResize(next_x, m_bevel,
button_size, button_size);
}
m_titlebar.raise(); // always on top
}
void FbWinFrame::renderAll() {
m_need_render = false;
renderTitlebar();
renderHandles();
2006-03-20 11:31:24 +00:00
renderTabContainer();
}
void FbWinFrame::applyAll() {
applyTitlebar();
applyHandles();
2006-03-20 11:31:24 +00:00
applyTabContainer();
}
2003-01-05 22:14:10 +00:00
void FbWinFrame::renderTitlebar() {
2003-09-12 22:49:14 +00:00
if (!m_use_titlebar)
2003-01-05 22:14:10 +00:00
return;
if (!isVisible()) {
m_need_render = true;
return;
}
2003-01-05 22:14:10 +00:00
// render pixmaps
render(m_theme.titleFocusTexture(), m_title_focused_color,
m_title_focused_pm,
m_titlebar.width(), m_titlebar.height());
render(m_theme.titleUnfocusTexture(), m_title_unfocused_color,
m_title_unfocused_pm,
m_titlebar.width(), m_titlebar.height());
2006-03-20 11:31:24 +00:00
//!! TODO: don't render label if internal tabs
2003-01-05 22:14:10 +00:00
render(m_theme.labelFocusTexture(), m_label_focused_color,
m_label_focused_pm,
2006-03-20 11:31:24 +00:00
m_label.width(), m_label.height());
2003-01-05 22:14:10 +00:00
render(m_theme.labelUnfocusTexture(), m_label_unfocused_color,
m_label_unfocused_pm,
2006-03-20 11:31:24 +00:00
m_label.width(), m_label.height());
2003-01-05 22:14:10 +00:00
renderButtons();
}
2003-12-09 08:48:08 +00:00
2006-03-20 11:31:24 +00:00
void FbWinFrame::renderTabContainer() {
if (!isVisible()) {
m_need_render = true;
return;
}
render(m_theme.labelFocusTexture(), m_tabcontainer_focused_color,
m_tabcontainer_focused_pm,
m_tab_container.width(), m_tab_container.height(), m_tab_container.orientation());
2006-03-20 11:31:24 +00:00
render(m_theme.labelUnfocusTexture(), m_tabcontainer_unfocused_color,
m_tabcontainer_unfocused_pm,
m_tab_container.width(), m_tab_container.height(), m_tab_container.orientation());
2006-03-20 11:31:24 +00:00
render(m_theme.labelFocusTexture(), m_labelbutton_focused_color,
m_labelbutton_focused_pm,
m_tab_container.width(), m_tab_container.height(), m_tab_container.orientation());
2006-03-20 11:31:24 +00:00
render(m_theme.labelUnfocusTexture(), m_labelbutton_unfocused_color,
m_labelbutton_unfocused_pm,
m_tab_container.width(), m_tab_container.height(), m_tab_container.orientation());
2006-03-20 11:31:24 +00:00
render(m_theme.labelActiveTexture(), m_labelbutton_active_color,
m_labelbutton_active_pm,
m_tab_container.width(), m_tab_container.height(), m_tab_container.orientation());
2006-03-20 11:31:24 +00:00
}
void FbWinFrame::applyTitlebar() {
2003-12-09 08:48:08 +00:00
// set up pixmaps for titlebar windows
2003-04-16 12:27:49 +00:00
Pixmap label_pm = None;
Pixmap title_pm = None;
FbTk::Color label_color;
FbTk::Color title_color;
getCurrentFocusPixmap(label_pm, title_pm,
label_color, title_color);
unsigned char alpha = (m_focused?theme().focusedAlpha():theme().unfocusedAlpha());
m_titlebar.setAlpha(alpha);
2006-03-20 11:31:24 +00:00
m_label.setAlpha(alpha);
if (m_tabmode != INTERNAL) {
2006-03-22 12:23:17 +00:00
m_label.setGC(m_focused?theme().labelTextFocusGC():theme().labelTextUnfocusGC());
2006-03-26 12:32:15 +00:00
m_label.setJustify(theme().justify());
2006-03-22 12:23:17 +00:00
2006-03-26 12:32:15 +00:00
if (label_pm != 0)
m_label.setBackgroundPixmap(label_pm);
else
m_label.setBackgroundColor(label_color);
}
2006-03-20 11:31:24 +00:00
2003-04-16 12:27:49 +00:00
if (title_pm != 0)
m_titlebar.setBackgroundPixmap(title_pm);
else
m_titlebar.setBackgroundColor(title_color);
2003-01-05 22:14:10 +00:00
applyButtons();
2003-01-05 22:14:10 +00:00
}
void FbWinFrame::renderHandles() {
2003-10-06 09:28:35 +00:00
if (!m_use_handle)
2003-01-05 22:14:10 +00:00
return;
2003-06-23 14:18:54 +00:00
if (!isVisible()) {
m_need_render = true;
return;
}
2003-01-05 22:14:10 +00:00
render(m_theme.handleFocusTexture(), m_handle_focused_color,
m_handle_focused_pm,
m_handle.width(), m_handle.height());
render(m_theme.handleUnfocusTexture(), m_handle_unfocused_color,
m_handle_unfocused_pm,
m_handle.width(), m_handle.height());
render(m_theme.gripFocusTexture(), m_grip_focused_color, m_grip_focused_pm,
m_grip_left.width(), m_grip_left.height());
render(m_theme.gripUnfocusTexture(), m_grip_unfocused_color,
m_grip_unfocused_pm,
m_grip_left.width(), m_grip_left.height());
}
void FbWinFrame::applyHandles() {
unsigned char alpha = (m_focused?theme().focusedAlpha():theme().unfocusedAlpha());
m_handle.setAlpha(alpha);
m_grip_left.setAlpha(alpha);
m_grip_right.setAlpha(alpha);
2003-01-05 22:14:10 +00:00
if (m_focused) {
if (m_handle_focused_pm) {
m_handle.setBackgroundPixmap(m_handle_focused_pm);
} else {
m_handle.setBackgroundColor(m_handle_focused_color);
}
2003-01-05 22:14:10 +00:00
if (m_grip_focused_pm) {
m_grip_left.setBackgroundPixmap(m_grip_focused_pm);
m_grip_right.setBackgroundPixmap(m_grip_focused_pm);
} else {
m_grip_left.setBackgroundColor(m_grip_focused_color);
m_grip_right.setBackgroundColor(m_grip_focused_color);
}
2003-01-05 22:14:10 +00:00
} else {
if (m_handle_unfocused_pm) {
m_handle.setBackgroundPixmap(m_handle_unfocused_pm);
} else {
m_handle.setBackgroundColor(m_handle_unfocused_color);
}
2003-01-05 22:14:10 +00:00
if (m_grip_unfocused_pm) {
m_grip_left.setBackgroundPixmap(m_grip_unfocused_pm);
m_grip_right.setBackgroundPixmap(m_grip_unfocused_pm);
} else {
m_grip_left.setBackgroundColor(m_grip_unfocused_color);
m_grip_right.setBackgroundColor(m_grip_unfocused_color);
}
}
2003-08-04 12:47:36 +00:00
2003-01-05 22:14:10 +00:00
}
void FbWinFrame::renderButtons() {
if (!isVisible()) {
m_need_render = true;
return;
}
render(m_theme.buttonFocusTexture(), m_button_color,
m_button_pm,
2003-01-05 22:14:10 +00:00
m_button_size, m_button_size);
2003-09-14 10:32:31 +00:00
2003-01-05 22:14:10 +00:00
render(m_theme.buttonUnfocusTexture(), m_button_unfocused_color,
m_button_unfocused_pm,
m_button_size, m_button_size);
render(m_theme.buttonPressedTexture(), m_button_pressed_color,
m_button_pressed_pm,
m_button_size, m_button_size);
}
2003-01-05 22:14:10 +00:00
void FbWinFrame::applyButtons() {
2003-01-05 22:14:10 +00:00
// setup left and right buttons
for (size_t i=0; i < m_buttons_left.size(); ++i)
applyButton(*m_buttons_left[i]);
2003-01-05 22:14:10 +00:00
for (size_t i=0; i < m_buttons_right.size(); ++i)
applyButton(*m_buttons_right[i]);
2003-01-05 22:14:10 +00:00
}
void FbWinFrame::init() {
if (FbTk::Transparent::haveComposite()) {
if (m_focused)
m_window.setOpaque(theme().focusedAlpha());
else
m_window.setOpaque(theme().unfocusedAlpha());
}
2003-06-23 14:18:54 +00:00
if (theme().handleWidth() == 0)
m_use_handle = false;
m_disable_shape = false;
2003-04-16 12:27:49 +00:00
m_current_label = 0; // no focused button at first
2003-06-23 14:18:54 +00:00
m_handle.showSubwindows();
2003-06-23 14:18:54 +00:00
// clear pixmaps
2003-01-05 22:14:10 +00:00
m_title_focused_pm = m_title_unfocused_pm = 0;
m_label_focused_pm = m_label_unfocused_pm = 0;
2006-03-20 11:31:24 +00:00
m_tabcontainer_focused_pm = m_tabcontainer_unfocused_pm = 0;
m_labelbutton_focused_pm = m_labelbutton_unfocused_pm = m_labelbutton_active_pm = 0;
2003-06-23 14:18:54 +00:00
m_handle_focused_pm = m_handle_unfocused_pm = 0;
m_button_pm = m_button_unfocused_pm = m_button_pressed_pm = 0;
m_grip_unfocused_pm = m_grip_focused_pm = 0;
m_double_click_time = 200;
2003-01-05 22:14:10 +00:00
m_button_size = 26;
2003-06-23 14:18:54 +00:00
2003-04-16 22:15:22 +00:00
m_clientarea.setBorderWidth(0);
2006-03-20 11:31:24 +00:00
m_label.setBorderWidth(0);
2003-01-05 22:14:10 +00:00
m_shaded = false;
2006-03-20 11:31:24 +00:00
setTabMode(NOTSET);
2006-03-20 11:31:24 +00:00
m_label.setEventMask(ExposureMask | ButtonPressMask |
ButtonReleaseMask | ButtonMotionMask |
EnterWindowMask);
2003-01-09 18:03:33 +00:00
showHandle();
showTitlebar();
2003-01-09 18:03:33 +00:00
2003-06-23 14:18:54 +00:00
// Note: we don't show clientarea yet
2003-01-05 22:14:10 +00:00
setEventHandler(*this);
}
/**
Setups upp background, pressed pixmap/color of the button to current theme
*/
void FbWinFrame::applyButton(FbTk::Button &btn) {
2003-09-14 10:32:31 +00:00
if (m_button_pressed_pm)
2003-01-05 22:14:10 +00:00
btn.setPressedPixmap(m_button_pressed_pm);
else
btn.setPressedColor(m_button_pressed_color);
2003-01-05 22:14:10 +00:00
2003-09-14 10:32:31 +00:00
if (focused()) { // focused
btn.setAlpha(theme().focusedAlpha());
2003-02-23 00:57:55 +00:00
btn.setGC(m_theme.buttonPicFocusGC());
2003-01-05 22:14:10 +00:00
if (m_button_pm)
btn.setBackgroundPixmap(m_button_pm);
else
btn.setBackgroundColor(m_button_color);
2003-09-14 10:32:31 +00:00
} else { // unfocused
btn.setAlpha(theme().unfocusedAlpha());
2003-02-23 00:57:55 +00:00
btn.setGC(m_theme.buttonPicUnfocusGC());
2003-01-05 22:14:10 +00:00
if (m_button_unfocused_pm)
btn.setBackgroundPixmap(m_button_unfocused_pm);
else
2003-09-14 10:32:31 +00:00
btn.setBackgroundColor(m_button_unfocused_color);
2003-01-05 22:14:10 +00:00
}
2003-08-04 12:47:36 +00:00
2003-01-05 22:14:10 +00:00
}
void FbWinFrame::render(const FbTk::Texture &tex, FbTk::Color &col, Pixmap &pm,
unsigned int w, unsigned int h, FbTk::Orientation orient) {
2003-10-09 16:48:09 +00:00
2003-01-05 22:14:10 +00:00
Pixmap tmp = pm;
2003-12-07 16:39:43 +00:00
if (!tex.usePixmap()) {
2003-01-05 22:14:10 +00:00
pm = None;
col = tex.color();
} else {
pm = m_imagectrl.renderImage(w, h, tex, orient);
}
2003-06-23 14:18:54 +00:00
2003-01-05 22:14:10 +00:00
if (tmp)
m_imagectrl.removeImage(tmp);
}
2003-04-16 12:27:49 +00:00
void FbWinFrame::getCurrentFocusPixmap(Pixmap &label_pm, Pixmap &title_pm,
2003-08-13 09:34:40 +00:00
FbTk::Color &label_color, FbTk::Color &title_color) {
2003-04-16 12:27:49 +00:00
if (m_focused) {
2006-03-20 11:31:24 +00:00
if (m_label_focused_pm != 0)
label_pm = m_label_focused_pm;
2003-04-16 12:27:49 +00:00
else
2006-03-20 11:31:24 +00:00
label_color = m_label_focused_color;
2003-04-16 12:27:49 +00:00
if (m_title_focused_pm != 0)
title_pm = m_title_focused_pm;
else
title_color = m_title_focused_color;
} else {
2006-03-20 11:31:24 +00:00
if (m_label_unfocused_pm != 0)
label_pm = m_label_unfocused_pm;
else
label_color = m_label_unfocused_color;
if (m_title_unfocused_pm != 0)
title_pm = m_title_unfocused_pm;
else
title_color = m_title_unfocused_color;
}
2003-04-16 12:27:49 +00:00
}
2006-03-20 11:31:24 +00:00
void FbWinFrame::applyTabContainer() {
m_tab_container.setAlpha(m_focused?theme().focusedAlpha():theme().unfocusedAlpha());
2003-04-16 12:27:49 +00:00
2006-03-20 11:31:24 +00:00
// do the parent container
Pixmap tabcontainer_pm = None;
FbTk::Color *tabcontainer_color = NULL;
if (m_focused) {
if (m_tabcontainer_focused_pm != 0)
tabcontainer_pm = m_tabcontainer_focused_pm;
else
tabcontainer_color = &m_tabcontainer_focused_color;
} else {
if (m_tabcontainer_unfocused_pm != 0)
tabcontainer_pm = m_tabcontainer_unfocused_pm;
else
tabcontainer_color = &m_tabcontainer_unfocused_color;
}
2003-10-09 16:48:09 +00:00
2006-03-20 11:31:24 +00:00
if (tabcontainer_pm != 0)
m_tab_container.setBackgroundPixmap(tabcontainer_pm);
else
m_tab_container.setBackgroundColor(*tabcontainer_color);
2003-04-16 12:27:49 +00:00
2006-03-20 11:31:24 +00:00
// and the labelbuttons in it
Container::ItemList::iterator btn_it = m_tab_container.begin();
Container::ItemList::iterator btn_it_end = m_tab_container.end();
2003-04-16 12:27:49 +00:00
for (; btn_it != btn_it_end; ++btn_it) {
FbTk::TextButton *btn = static_cast<FbTk::TextButton *>(*btn_it);
if (btn == m_current_label) {
2003-12-09 08:48:08 +00:00
if (m_focused)
applyFocusLabel(*btn);
2003-12-09 08:48:08 +00:00
else
applyActiveLabel(*btn);
2003-12-09 08:48:08 +00:00
} else
applyUnfocusLabel(*btn);
2003-04-16 12:27:49 +00:00
}
}
void FbWinFrame::setBorderWidth(unsigned int border_width) {
int bw_changes = 0;
// we need to change the size of the window
// if the border width changes...
if (m_use_titlebar)
bw_changes += static_cast<signed>(border_width - titlebar().borderWidth());
if (m_use_handle)
bw_changes += static_cast<signed>(border_width - handle().borderWidth());
window().setBorderWidth(border_width);
window().setBorderColor(theme().border().color());
2003-08-25 13:15:53 +00:00
2006-03-20 11:31:24 +00:00
setTabMode(NOTSET);
titlebar().setBorderWidth(border_width);
titlebar().setBorderColor(theme().border().color());
2003-08-25 13:15:53 +00:00
handle().setBorderWidth(border_width);
handle().setBorderColor(theme().border().color());
2003-08-25 13:15:53 +00:00
gripLeft().setBorderWidth(border_width);
gripLeft().setBorderColor(theme().border().color());
2003-08-25 13:15:53 +00:00
gripRight().setBorderWidth(border_width);
gripRight().setBorderColor(theme().border().color());
// and the labelbuttons
Container::ItemList::iterator btn_it = m_tab_container.begin();
Container::ItemList::iterator btn_it_end = m_tab_container.end();
for (; btn_it != btn_it_end; ++btn_it) {
(*btn_it)->setBorderWidth(border_width);
(*btn_it)->setBorderColor(theme().border().color());
}
m_tab_container.update();
if (bw_changes != 0)
resize(width(), height() + bw_changes);
2006-03-20 11:31:24 +00:00
if (m_tabmode == EXTERNAL)
alignTabs();
}
2003-08-04 12:47:36 +00:00
void FbWinFrame::applyFocusLabel(FbTk::TextButton &button) {
button.setGC(theme().labelTextFocusGC());
button.setJustify(theme().justify());
button.setAlpha(m_focused?theme().focusedAlpha():theme().unfocusedAlpha());
if (m_labelbutton_focused_pm != 0) {
button.setBackgroundPixmap(m_labelbutton_focused_pm);
2003-09-12 22:49:14 +00:00
} else
button.setBackgroundColor(m_labelbutton_focused_color);
}
void FbWinFrame::applyActiveLabel(FbTk::TextButton &button) {
2006-03-22 12:23:17 +00:00
2003-12-09 08:48:08 +00:00
button.setGC(theme().labelTextActiveGC());
button.setJustify(theme().justify());
button.setAlpha(m_focused?theme().focusedAlpha():theme().unfocusedAlpha());
2003-12-09 08:48:08 +00:00
if (m_labelbutton_active_pm != 0) {
button.setBackgroundPixmap(m_labelbutton_active_pm);
2003-12-09 08:48:08 +00:00
} else
button.setBackgroundColor(m_labelbutton_active_color);
2003-12-09 08:48:08 +00:00
}
void FbWinFrame::applyUnfocusLabel(FbTk::TextButton &button) {
2003-10-09 16:48:09 +00:00
button.setGC(theme().labelTextUnfocusGC());
button.setJustify(theme().justify());
button.setAlpha(m_focused?theme().focusedAlpha():theme().unfocusedAlpha());
if (m_labelbutton_unfocused_pm != 0) {
button.setBackgroundPixmap(m_labelbutton_unfocused_pm);
2003-09-12 22:49:14 +00:00
} else
button.setBackgroundColor(m_labelbutton_unfocused_color);
}
2004-02-28 16:54:04 +00:00
namespace {
class IgnoreEvent {
public:
typedef void result_type;
typedef Window argument_type;
explicit IgnoreEvent(long eventmask):
m_display(FbTk::App::instance()->display()),
m_event_mask(eventmask) {
}
void operator()(Window win) const {
static XEvent event;
while (XCheckWindowEvent(m_display, win, m_event_mask, &event))
continue;
}
private:
Display *m_display;
long m_event_mask;
};
}
2003-09-11 13:17:14 +00:00
// this function translates its arguments according to win_gravity
// if win_gravity is negative, it does an inverse translation
2003-09-11 19:55:27 +00:00
// This function should be used when a window is mapped/unmapped/pos configured
2003-09-11 13:17:14 +00:00
void FbWinFrame::gravityTranslate(int &x, int &y, int win_gravity, bool move_frame) {
gravityTranslate(x, y, m_window.width(), m_window.height(), win_gravity, move_frame);
}
//use width and height given instead of the real values, allows figuring out where to place a window before doing a moveResize
void FbWinFrame::gravityTranslate(int &x, int &y, unsigned int width, unsigned int height, int win_gravity, bool move_frame) {
2003-09-11 13:17:14 +00:00
bool invert = false;
if (win_gravity < 0) {
invert = true;
win_gravity = -win_gravity; // make +ve
}
/* Ok, so, gravity says which point of the frame is put where the
* corresponding bit of window would have been
* Thus, x,y always refers to where top left of the WINDOW would be placed
* but given that we're wrapping it in a frame, we actually place
* it so that the given reference point is in the same spot as the
* window's reference point would have been.
* i.e. east gravity says that the centre of the right hand side of the
* frame is placed where the centre of the rhs of the window would
* have been if there was no frame.
* Hope that makes enough sense.
*
* If you get confused with the calculations, draw a picture.
*
*/
// We calculate offsets based on the gravity and frame aspects
// and at the end apply those offsets +ve or -ve depending on 'invert'
int x_offset = 0;
int y_offset = 0;
/* win_gravity: placed at the reference point
* StaticGravity the left top corner of the client window
* NorthWestGravity the left top corner of the frame window
* NorthGravity the center of the frame window's top side
* NorthEastGravity the right top corner of the frame window
* EastGravity the center of the frame window's right side
* SouthEastGravity the right bottom corner of the frame window
* SouthGravity the center of the frame window's bottom side
* SouthWestGravity the left bottom corner of the frame window
* WestGravity the center of the frame window's left side
* CenterGravity the center of the frame window
*/
//vertical offset
//North Gravities don't require a vertical offset
//South Gravities
if (win_gravity==SouthWestGravity || win_gravity==SouthGravity ||
win_gravity==SouthEastGravity) {
//We start on the frame so going the full height would take us one pixel past the edge of the frame
y_offset-=height-1;
}
//vertical centering
if (win_gravity==WestGravity || win_gravity==CenterGravity ||
win_gravity==EastGravity) {
y_offset-=height/2;
}
//horizontal offset
//West Gravities don't require a horizontal offset
//East Gravities
if (win_gravity==NorthEastGravity || win_gravity==EastGravity ||
win_gravity==SouthEastGravity ) {
//Starting on the frame so offset of one width would end up one pixel beyond the border
x_offset-=width-1;
}
//horizontal centering
if (win_gravity==NorthGravity || win_gravity==CenterGravity ||
win_gravity==SouthGravity ) {
x_offset-=width/2;
}
if( win_gravity==StaticGravity ) {
2003-09-16 13:11:42 +00:00
if (m_use_titlebar)
y_offset -= m_titlebar.height() + m_titlebar.borderWidth();
x_offset -= m_window.borderWidth();
y_offset -= m_window.borderWidth();
2003-09-11 13:17:14 +00:00
}
2003-09-11 13:17:14 +00:00
if (invert) {
x_offset = -x_offset;
y_offset = -y_offset;
}
x += x_offset;
y += y_offset;
if (move_frame && (x_offset != 0 || y_offset != 0)) {
2004-08-11 13:17:56 +00:00
move(x, y);
2003-09-11 13:17:14 +00:00
}
}
2006-03-20 11:31:24 +00:00
int FbWinFrame::widthOffset() const {
2006-03-22 12:23:17 +00:00
if (m_tabmode != EXTERNAL || !m_use_tabs)
2006-03-20 11:31:24 +00:00
return 0;
2006-03-22 12:23:17 +00:00
// same height offset for top and bottom tabs
switch (m_screen.getTabPlacement()) {
case LEFTTOP:
case RIGHTTOP:
case LEFTBOTTOM:
case RIGHTBOTTOM:
return m_tab_container.width() + m_window.borderWidth();
break;
2006-04-16 11:18:22 +00:00
default: // kill warning
break;
}
return 0;
2006-03-20 11:31:24 +00:00
}
int FbWinFrame::heightOffset() const {
2006-03-22 12:23:17 +00:00
if (m_tabmode != EXTERNAL || !m_use_tabs)
return 0;
switch (m_screen.getTabPlacement()) {
2006-03-22 12:23:17 +00:00
case TOPLEFT:
case TOPRIGHT:
case BOTTOMLEFT:
case BOTTOMRIGHT:
return m_tab_container.height() + m_window.borderWidth();
break;
2006-04-16 11:18:22 +00:00
default: // kill warning
break;
}
return 0;
}
int FbWinFrame::xOffset() const {
if (m_tabmode != EXTERNAL || !m_use_tabs)
2006-03-20 11:31:24 +00:00
return 0;
switch (m_screen.getTabPlacement()) {
case LEFTTOP:
case LEFTBOTTOM:
return m_tab_container.width() + m_window.borderWidth();
break;
2006-04-16 11:18:22 +00:00
default: // kill warning
break;
}
return 0;
}
int FbWinFrame::yOffset() const {
if (m_tabmode != EXTERNAL || !m_use_tabs)
return 0;
switch (m_screen.getTabPlacement()) {
case TOPLEFT:
case TOPRIGHT:
return m_tab_container.height() + m_window.borderWidth();
2006-03-22 12:23:17 +00:00
break;
2006-04-16 11:18:22 +00:00
default: // kill warning
break;
2006-03-22 12:23:17 +00:00
}
return 0;
2006-03-20 11:31:24 +00:00
}