fluxbox/src/Slit.cc

1104 lines
27 KiB
C++
Raw Normal View History

2001-12-11 20:47:02 +00:00
// Slit.cc for Blackbox - an X11 Window manager
// Copyright (c) 1997 - 2000 Brad Hughes (bhughes@tcac.net)
//
// 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.
2002-09-08 19:48:03 +00:00
// $Id: Slit.cc,v 1.21 2002/09/08 19:48:03 fluxgen Exp $
2002-04-08 18:58:47 +00:00
2002-03-11 12:29:57 +00:00
//use GNU extensions
2001-12-11 20:47:02 +00:00
#ifndef _GNU_SOURCE
#define _GNU_SOURCE
#endif // _GNU_SOURCE
#ifdef HAVE_CONFIG_H
# include "../config.h"
#endif // HAVE_CONFIG_H
#ifdef SLIT
#include <X11/keysym.h>
#include "i18n.hh"
#include "fluxbox.hh"
#include "Image.hh"
#include "Screen.hh"
#include "Slit.hh"
#include "Toolbar.hh"
2002-02-04 22:33:09 +00:00
#include <algorithm>
2002-05-29 06:21:59 +00:00
#include <iostream>
#include <cassert>
2002-02-04 22:33:09 +00:00
2002-05-29 06:21:59 +00:00
#ifdef HAVE_SYS_STAT_H
# include <sys/types.h>
# include <sys/stat.h>
#endif // HAVE_SYS_STAT_H
// Utility method for extracting name from window
namespace {
void getWMName(BScreen *screen, Window window, std::string& name) {
name = "";
if (screen != 0 && window != None) {
Display *display = screen->getBaseDisplay()->getXDisplay();
XTextProperty text_prop;
char **list;
int num;
I18n *i18n = I18n::instance();
if (XGetWMName(display, window, &text_prop)) {
if (text_prop.value && text_prop.nitems > 0) {
if (text_prop.encoding != XA_STRING) {
text_prop.nitems = strlen((char *) text_prop.value);
if ((XmbTextPropertyToTextList(display, &text_prop,
&list, &num) == Success) &&
(num > 0) && *list) {
name = static_cast<char *>(*list);
XFreeStringList(list);
} else
name = (char *)text_prop.value;
} else
name = (char *)text_prop.value;
} else
name = i18n->getMessage(
FBNLS::WindowSet, FBNLS::WindowUnnamed,
"Unnamed");
} else {
name = i18n->getMessage(
FBNLS::WindowSet, FBNLS::WindowUnnamed,
"Unnamed");
}
}
}
}; // End anonymous namespace
2001-12-11 20:47:02 +00:00
2002-05-08 14:12:28 +00:00
Slit::Slit(BScreen *scr):screen(scr), timer(this), slitmenu(*this) {
2002-05-29 06:21:59 +00:00
assert(scr);
2001-12-11 20:47:02 +00:00
fluxbox = Fluxbox::instance();
on_top = screen->isSlitOnTop();
hidden = do_auto_hide = screen->doSlitAutoHide();
display = screen->getBaseDisplay()->getXDisplay();
frame.window = frame.pixmap = None;
2002-03-19 00:07:00 +00:00
timer.setTimeout(fluxbox->getAutoRaiseDelay());
timer.fireOnce(True);
2001-12-11 20:47:02 +00:00
XSetWindowAttributes attrib;
unsigned long create_mask = CWBackPixmap | CWBackPixel | CWBorderPixel |
2002-02-04 22:33:09 +00:00
CWColormap | CWOverrideRedirect | CWEventMask;
2001-12-11 20:47:02 +00:00
attrib.background_pixmap = None;
attrib.background_pixel = attrib.border_pixel =
2002-07-20 09:35:01 +00:00
screen->getBorderColor()->pixel();
attrib.colormap = screen->colormap();
2001-12-11 20:47:02 +00:00
attrib.override_redirect = True;
attrib.event_mask = SubstructureRedirectMask | ButtonPressMask |
2002-05-29 06:21:59 +00:00
EnterWindowMask | LeaveWindowMask;
2001-12-11 20:47:02 +00:00
frame.x = frame.y = 0;
frame.width = frame.height = 1;
frame.window =
XCreateWindow(display, screen->getRootWindow(), frame.x, frame.y,
frame.width, frame.height, screen->getBorderWidth(),
2002-03-11 12:29:57 +00:00
screen->getDepth(), InputOutput, screen->getVisual(),
create_mask, &attrib);
2001-12-11 20:47:02 +00:00
fluxbox->saveSlitSearch(frame.window, this);
2002-05-29 06:21:59 +00:00
// Get client list for sorting purposes
loadClientList();
2001-12-11 20:47:02 +00:00
reconfigure();
}
Slit::~Slit() {
fluxbox->grab();
screen->getImageControl()->removeImage(frame.pixmap);
fluxbox->removeSlitSearch(frame.window);
XDestroyWindow(display, frame.window);
fluxbox->ungrab();
}
void Slit::addClient(Window w) {
2002-05-08 14:12:28 +00:00
//Can't add non existent window
if (w == None)
return;
2001-12-11 20:47:02 +00:00
fluxbox->grab();
if (fluxbox->validateWindow(w)) {
2002-05-29 06:21:59 +00:00
// Look for slot in client list by name
SlitClient *client = 0;
std::string match_name;
::getWMName(screen, w, match_name);
SlitClients::iterator it = clientList.begin();
SlitClients::iterator it_end = clientList.end();
bool found_match = false;
for (; it != it_end; ++it) {
// If the name matches...
if ((*it)->match_name == match_name) {
// Use the slot if no window is assigned
if ((*it)->window == None) {
client = (*it);
client->initialize(screen, w);
break;
}
// Otherwise keep looking for an unused match or a non-match
found_match = true; // Possibly redundant
} else if (found_match) {
// Insert before first non-match after a previously found match?
client = new SlitClient(screen, w);
clientList.insert(it, client);
break;
}
}
// Append to client list?
if (client == 0) {
client = new SlitClient(screen, w);
clientList.push_back(client);
}
2001-12-11 20:47:02 +00:00
XWMHints *wmhints = XGetWMHints(display, w);
if (wmhints) {
if ((wmhints->flags & IconWindowHint) &&
(wmhints->icon_window != None)) {
XMoveWindow(display, client->client_window, screen->getWidth() + 10,
2002-02-04 22:33:09 +00:00
screen->getHeight() + 10);
XMapWindow(display, client->client_window);
2001-12-11 20:47:02 +00:00
client->icon_window = wmhints->icon_window;
client->window = client->icon_window;
} else {
client->icon_window = None;
client->window = client->client_window;
}
XFree(wmhints);
} else {
client->icon_window = None;
client->window = client->client_window;
}
XWindowAttributes attrib;
2002-03-11 12:29:57 +00:00
#ifdef KDE
2001-12-11 20:47:02 +00:00
//Check and see if new client is a KDE dock applet
//If so force reasonable size
bool iskdedockapp=false;
Atom ajunk;
int ijunk;
unsigned long *data = (unsigned long *) 0, uljunk;
// Check if KDE v2.x dock applet
if (XGetWindowProperty(fluxbox->getXDisplay(), w,
2002-02-04 22:33:09 +00:00
fluxbox->getKWM2DockwindowAtom(), 0l, 1l, False,
fluxbox->getKWM2DockwindowAtom(),
&ajunk, &ijunk, &uljunk, &uljunk,
(unsigned char **) &data) == Success) {
2001-12-11 20:47:02 +00:00
iskdedockapp = (data && data[0] != 0);
XFree((char *) data);
2002-02-04 22:33:09 +00:00
}
2001-12-11 20:47:02 +00:00
// Check if KDE v1.x dock applet
if (!iskdedockapp) {
if (XGetWindowProperty(fluxbox->getXDisplay(), w,
2002-02-04 22:33:09 +00:00
fluxbox->getKWM1DockwindowAtom(), 0l, 1l, False,
fluxbox->getKWM1DockwindowAtom(),
&ajunk, &ijunk, &uljunk, &uljunk,
(unsigned char **) &data) == Success) {
2001-12-11 20:47:02 +00:00
iskdedockapp = (data && data[0] != 0);
2002-02-04 22:33:09 +00:00
XFree((char *) data);
}
2001-12-11 20:47:02 +00:00
}
if (iskdedockapp)
client->width = client->height = 24;
2002-03-11 12:29:57 +00:00
else
#endif // KDE
{
2001-12-11 20:47:02 +00:00
if (XGetWindowAttributes(display, client->window, &attrib)) {
client->width = attrib.width;
client->height = attrib.height;
2002-03-11 12:29:57 +00:00
} else {
2001-12-11 20:47:02 +00:00
client->width = client->height = 64;
2002-03-11 12:29:57 +00:00
}
2001-12-11 20:47:02 +00:00
}
XSetWindowBorderWidth(display, client->window, 0);
XSelectInput(display, frame.window, NoEventMask);
XSelectInput(display, client->window, NoEventMask);
XReparentWindow(display, client->window, frame.window, 0, 0);
2002-02-04 22:33:09 +00:00
XMapRaised(display, client->window);
2001-12-11 20:47:02 +00:00
XChangeSaveSet(display, client->window, SetModeInsert);
XSelectInput(display, frame.window, SubstructureRedirectMask |
2002-02-04 22:33:09 +00:00
ButtonPressMask | EnterWindowMask | LeaveWindowMask);
2001-12-11 20:47:02 +00:00
XSelectInput(display, client->window, StructureNotifyMask |
2002-02-04 22:33:09 +00:00
SubstructureNotifyMask | EnterWindowMask);
2001-12-11 20:47:02 +00:00
XFlush(display);
fluxbox->saveSlitSearch(client->client_window, this);
fluxbox->saveSlitSearch(client->icon_window, this);
reconfigure();
2002-05-29 06:21:59 +00:00
saveClientList();
2001-12-11 20:47:02 +00:00
}
fluxbox->ungrab();
}
2002-05-29 06:21:59 +00:00
void Slit::removeClient(SlitClient *client, bool remap, bool destroy) {
2001-12-11 20:47:02 +00:00
fluxbox->removeSlitSearch(client->client_window);
fluxbox->removeSlitSearch(client->icon_window);
2002-02-04 22:33:09 +00:00
2002-05-29 06:21:59 +00:00
// Destructive removal?
if (destroy)
clientList.remove(client);
else // Clear the window info, but keep around to help future sorting?
client->initialize();
2001-12-11 20:47:02 +00:00
screen->removeNetizen(client->window);
if (remap && fluxbox->validateWindow(client->window)) {
XSelectInput(display, frame.window, NoEventMask);
XSelectInput(display, client->window, NoEventMask);
XReparentWindow(display, client->window, screen->getRootWindow(),
2002-02-04 22:33:09 +00:00
client->x, client->y);
2001-12-11 20:47:02 +00:00
XChangeSaveSet(display, client->window, SetModeDelete);
XSelectInput(display, frame.window, SubstructureRedirectMask |
2002-02-04 22:33:09 +00:00
ButtonPressMask | EnterWindowMask | LeaveWindowMask);
2001-12-11 20:47:02 +00:00
XFlush(display);
}
2002-05-29 06:21:59 +00:00
// Destructive removal?
if (destroy)
delete client;
2001-12-11 20:47:02 +00:00
}
2002-02-04 22:33:09 +00:00
void Slit::removeClient(Window w, bool remap) {
2001-12-11 20:47:02 +00:00
fluxbox->grab();
2002-02-04 22:33:09 +00:00
bool reconf = false;
2001-12-11 20:47:02 +00:00
2002-02-04 22:33:09 +00:00
SlitClients::iterator it = clientList.begin();
SlitClients::iterator it_end = clientList.end();
for (; it != it_end; ++it) {
if ((*it)->window == w) {
2002-05-29 06:21:59 +00:00
removeClient((*it), remap, false);
2002-02-04 22:33:09 +00:00
reconf = true;
2001-12-11 20:47:02 +00:00
break;
}
2002-02-04 22:33:09 +00:00
}
2001-12-11 20:47:02 +00:00
if (reconf) reconfigure();
fluxbox->ungrab();
}
void Slit::reconfigure(void) {
frame.width = 0;
frame.height = 0;
2002-05-29 06:21:59 +00:00
// Need to count windows because not all client list entries
// actually correspond to mapped windows.
int num_windows = 0;
2001-12-11 20:47:02 +00:00
switch (screen->getSlitDirection()) {
2002-01-11 10:21:44 +00:00
case VERTICAL:
2002-02-04 22:33:09 +00:00
{
SlitClients::iterator it = clientList.begin();
SlitClients::iterator it_end = clientList.end();
for (; it != it_end; ++it) {
2002-05-29 06:21:59 +00:00
//client created window?
if ((*it)->window != None) {
num_windows++;
frame.height += (*it)->height + screen->getBevelWidth();
//frame width < client window?
if (frame.width < (*it)->width)
frame.width = (*it)->width;
}
2002-02-04 22:33:09 +00:00
}
2001-12-11 20:47:02 +00:00
}
if (frame.width < 1)
frame.width = 1;
else
frame.width += (screen->getBevelWidth() * 2);
if (frame.height < 1)
frame.height = 1;
else
frame.height += screen->getBevelWidth();
break;
2002-01-11 10:21:44 +00:00
case HORIZONTAL:
2002-02-04 22:33:09 +00:00
{
SlitClients::iterator it = clientList.begin();
SlitClients::iterator it_end = clientList.end();
for (; it != it_end; ++it) {
2002-05-29 06:21:59 +00:00
//client created window?
if ((*it)->window != None) {
num_windows++;
frame.width += (*it)->width + screen->getBevelWidth();
//frame height < client height?
if (frame.height < (*it)->height)
frame.height = (*it)->height;
}
2002-02-04 22:33:09 +00:00
}
2001-12-11 20:47:02 +00:00
}
if (frame.width < 1)
frame.width = 1;
else
frame.width += screen->getBevelWidth();
if (frame.height < 1)
frame.height = 1;
else
frame.height += (screen->getBevelWidth() * 2);
break;
}
reposition();
XSetWindowBorderWidth(display ,frame.window, screen->getBorderWidth());
XSetWindowBorder(display, frame.window,
2002-07-20 09:35:01 +00:00
screen->getBorderColor()->pixel());
2001-12-11 20:47:02 +00:00
2002-05-29 06:21:59 +00:00
//did we actually use slit slots
if (num_windows == 0)
2001-12-11 20:47:02 +00:00
XUnmapWindow(display, frame.window);
else
XMapWindow(display, frame.window);
Pixmap tmp = frame.pixmap;
BImageControl *image_ctrl = screen->getImageControl();
const FbTk::Texture *texture = &(screen->getTheme()->getSlitTexture());
if (texture->type() == (FbTk::Texture::FLAT | FbTk::Texture::SOLID)) {
2001-12-11 20:47:02 +00:00
frame.pixmap = None;
XSetWindowBackground(display, frame.window,
2002-07-20 09:35:01 +00:00
texture->color().pixel());
2001-12-11 20:47:02 +00:00
} else {
frame.pixmap = image_ctrl->renderImage(frame.width, frame.height,
2002-02-04 22:33:09 +00:00
texture);
2001-12-11 20:47:02 +00:00
XSetWindowBackgroundPixmap(display, frame.window, frame.pixmap);
}
2002-05-29 06:21:59 +00:00
if (tmp)
image_ctrl->removeImage(tmp);
2001-12-11 20:47:02 +00:00
XClearWindow(display, frame.window);
int x, y;
switch (screen->getSlitDirection()) {
2002-01-11 10:21:44 +00:00
case VERTICAL:
2001-12-11 20:47:02 +00:00
x = 0;
y = screen->getBevelWidth();
2002-02-04 22:33:09 +00:00
{
SlitClients::iterator it = clientList.begin();
SlitClients::iterator it_end = clientList.end();
for (; it != it_end; ++it) {
2002-05-29 06:21:59 +00:00
//client created window?
if ((*it)->window == None)
continue;
2002-02-04 22:33:09 +00:00
x = (frame.width - (*it)->width) / 2;
XMoveResizeWindow(display, (*it)->window, x, y,
(*it)->width, (*it)->height);
XMapWindow(display, (*it)->window);
// for ICCCM compliance
(*it)->x = x;
(*it)->y = y;
XEvent event;
event.type = ConfigureNotify;
event.xconfigure.display = display;
event.xconfigure.event = (*it)->window;
event.xconfigure.window = (*it)->window;
event.xconfigure.x = x;
event.xconfigure.y = y;
event.xconfigure.width = (*it)->width;
event.xconfigure.height = (*it)->height;
event.xconfigure.border_width = 0;
event.xconfigure.above = frame.window;
event.xconfigure.override_redirect = False;
XSendEvent(display, (*it)->window, False, StructureNotifyMask,
&event);
y += (*it)->height + screen->getBevelWidth();
}
2001-12-11 20:47:02 +00:00
}
break;
2002-01-11 10:21:44 +00:00
case HORIZONTAL:
2001-12-11 20:47:02 +00:00
x = screen->getBevelWidth();
y = 0;
2002-02-04 22:33:09 +00:00
{
SlitClients::iterator it = clientList.begin();
SlitClients::iterator it_end = clientList.end();
for (; it != it_end; ++it) {
2002-05-29 06:21:59 +00:00
//client created window?
if ((*it)->window == None)
continue;
2002-02-04 22:33:09 +00:00
y = (frame.height - (*it)->height) / 2;
XMoveResizeWindow(display, (*it)->window, x, y,
(*it)->width, (*it)->height);
XMapWindow(display, (*it)->window);
// for ICCCM compliance
(*it)->x = x;
(*it)->y = y;
XEvent event;
event.type = ConfigureNotify;
event.xconfigure.display = display;
event.xconfigure.event = (*it)->window;
event.xconfigure.window = (*it)->window;
event.xconfigure.x = frame.x + x + screen->getBorderWidth();
event.xconfigure.y = frame.y + y + screen->getBorderWidth();
event.xconfigure.width = (*it)->width;
event.xconfigure.height = (*it)->height;
event.xconfigure.border_width = 0;
event.xconfigure.above = frame.window;
event.xconfigure.override_redirect = False;
XSendEvent(display, (*it)->window, False, StructureNotifyMask,
&event);
x += (*it)->width + screen->getBevelWidth();
}
2001-12-11 20:47:02 +00:00
}
break;
}
2002-03-19 00:07:00 +00:00
slitmenu.reconfigure();
2001-12-11 20:47:02 +00:00
}
2002-08-14 21:51:07 +00:00
void Slit::reposition() {
2002-03-19 14:30:43 +00:00
int head_x = 0,
head_y = 0,
head_w,
head_h;
#ifdef XINERAMA
2002-03-19 14:30:43 +00:00
if (screen->hasXinerama()) {
unsigned int head = screen->getSlitOnHead();
head_x = screen->getHeadX(head);
head_y = screen->getHeadY(head);
head_w = screen->getHeadWidth(head);
head_h = screen->getHeadHeight(head);
} else {
head_w = screen->getWidth();
head_h = screen->getHeight();
}
#else // !XINERAMA
head_w = screen->getWidth();
head_h = screen->getHeight();
#endif // XINERAMA
2001-12-11 20:47:02 +00:00
// place the slit in the appropriate place
switch (screen->getSlitPlacement()) {
2002-01-11 10:21:44 +00:00
case TOPLEFT:
2002-03-19 14:30:43 +00:00
frame.x = head_x;
frame.y = head_y;
2002-01-11 10:21:44 +00:00
if (screen->getSlitDirection() == VERTICAL) {
2002-02-04 22:33:09 +00:00
frame.x_hidden = screen->getBevelWidth() -
screen->getBorderWidth() - frame.width;
2002-03-19 14:30:43 +00:00
frame.y_hidden = head_y;
2001-12-11 20:47:02 +00:00
} else {
2002-03-19 14:30:43 +00:00
frame.x_hidden = head_x;
2002-02-04 22:33:09 +00:00
frame.y_hidden = screen->getBevelWidth() -
screen->getBorderWidth() - frame.height;
2001-12-11 20:47:02 +00:00
}
break;
2002-01-11 10:21:44 +00:00
case CENTERLEFT:
2002-03-19 14:30:43 +00:00
frame.x = head_x;
frame.y = head_y + (head_h - frame.height) / 2;
frame.x_hidden = head_x + screen->getBevelWidth() -
2002-02-04 22:33:09 +00:00
screen->getBorderWidth() - frame.width;
2001-12-11 20:47:02 +00:00
frame.y_hidden = frame.y;
break;
2002-01-11 10:21:44 +00:00
case BOTTOMLEFT:
2002-03-19 14:30:43 +00:00
frame.x = head_x;
frame.y = head_h - frame.height - screen->getBorderWidth2x();
2002-01-11 10:21:44 +00:00
if (screen->getSlitDirection() == VERTICAL) {
2002-03-19 14:30:43 +00:00
frame.x_hidden = head_x + screen->getBevelWidth() -
screen->getBorderWidth() - frame.width;
2001-12-11 20:47:02 +00:00
frame.y_hidden = frame.y;
} else {
2002-03-19 14:30:43 +00:00
frame.x_hidden = head_x;
frame.y_hidden = head_y + head_h -
2002-02-04 22:33:09 +00:00
screen->getBevelWidth() - screen->getBorderWidth();
2001-12-11 20:47:02 +00:00
}
break;
2002-01-11 10:21:44 +00:00
case TOPCENTER:
2002-03-19 14:30:43 +00:00
frame.x = head_x + ((head_w - frame.width) / 2);
frame.y = head_y;
2001-12-11 20:47:02 +00:00
frame.x_hidden = frame.x;
2002-03-19 14:30:43 +00:00
frame.y_hidden = head_y + screen->getBevelWidth() -
2002-02-04 22:33:09 +00:00
screen->getBorderWidth() - frame.height;
2001-12-11 20:47:02 +00:00
break;
2002-01-11 10:21:44 +00:00
case BOTTOMCENTER:
2002-03-19 14:30:43 +00:00
frame.x = head_x + ((head_w - frame.width) / 2);
frame.y = head_y + head_h - frame.height - screen->getBorderWidth2x();
2001-12-11 20:47:02 +00:00
frame.x_hidden = frame.x;
2002-03-19 14:30:43 +00:00
frame.y_hidden = head_y + head_h -
2002-02-04 22:33:09 +00:00
screen->getBevelWidth() - screen->getBorderWidth();
2001-12-11 20:47:02 +00:00
break;
2002-01-11 10:21:44 +00:00
case TOPRIGHT:
2002-03-19 14:30:43 +00:00
frame.x = head_x + head_w - frame.width - screen->getBorderWidth2x();
frame.y = head_y;
2002-01-11 10:21:44 +00:00
if (screen->getSlitDirection() == VERTICAL) {
2002-03-19 14:30:43 +00:00
frame.x_hidden = head_x + head_w -
2002-02-04 22:33:09 +00:00
screen->getBevelWidth() - screen->getBorderWidth();
2002-03-19 14:30:43 +00:00
frame.y_hidden = head_y;
2001-12-11 20:47:02 +00:00
} else {
frame.x_hidden = frame.x;
2002-03-19 14:30:43 +00:00
frame.y_hidden = head_y + screen->getBevelWidth() -
2002-02-04 22:33:09 +00:00
screen->getBorderWidth() - frame.height;
2001-12-11 20:47:02 +00:00
}
break;
2002-01-11 10:21:44 +00:00
case CENTERRIGHT:
2001-12-11 20:47:02 +00:00
default:
2002-03-19 14:30:43 +00:00
frame.x = head_x + head_w - frame.width - screen->getBorderWidth2x();
frame.y = head_y + ((head_h - frame.height) / 2);
frame.x_hidden = head_x + head_w -
2002-02-04 22:33:09 +00:00
screen->getBevelWidth() - screen->getBorderWidth();
2001-12-11 20:47:02 +00:00
frame.y_hidden = frame.y;
break;
2002-01-11 10:21:44 +00:00
case BOTTOMRIGHT:
2002-03-19 14:30:43 +00:00
frame.x = head_x + head_w - frame.width - screen->getBorderWidth2x();
frame.y = head_y + head_h - frame.height - screen->getBorderWidth2x();
2002-01-11 10:21:44 +00:00
if (screen->getSlitDirection() == VERTICAL) {
2002-03-19 14:30:43 +00:00
frame.x_hidden = head_x + head_w -
2002-02-04 22:33:09 +00:00
screen->getBevelWidth() - screen->getBorderWidth();
2001-12-11 20:47:02 +00:00
frame.y_hidden = frame.y;
} else {
frame.x_hidden = frame.x;
2002-03-19 14:30:43 +00:00
frame.y_hidden = head_y + head_h -
2002-02-04 22:33:09 +00:00
screen->getBevelWidth() - screen->getBorderWidth();
2001-12-11 20:47:02 +00:00
}
break;
}
Toolbar *tbar = screen->getToolbar();
int sw = frame.width + screen->getBorderWidth2x(),
2002-02-04 22:33:09 +00:00
sh = frame.height + screen->getBorderWidth2x(),
tw = tbar->getWidth() + screen->getBorderWidth(),
th = tbar->getHeight() + screen->getBorderWidth();
2001-12-11 20:47:02 +00:00
if (tbar->getX() < frame.x + sw && tbar->getX() + tw > frame.x &&
tbar->getY() < frame.y + sh && tbar->getY() + th > frame.y) {
if (frame.y < th) {
frame.y += tbar->getExposedHeight();
2002-01-11 10:21:44 +00:00
if (screen->getSlitDirection() == VERTICAL)
2001-12-11 20:47:02 +00:00
frame.y_hidden += tbar->getExposedHeight();
else
2002-02-04 22:33:09 +00:00
frame.y_hidden = frame.y;
2001-12-11 20:47:02 +00:00
} else {
frame.y -= tbar->getExposedHeight();
2002-01-11 10:21:44 +00:00
if (screen->getSlitDirection() == VERTICAL)
2001-12-11 20:47:02 +00:00
frame.y_hidden -= tbar->getExposedHeight();
else
2002-02-04 22:33:09 +00:00
frame.y_hidden = frame.y;
2001-12-11 20:47:02 +00:00
}
}
if (hidden)
XMoveResizeWindow(display, frame.window, frame.x_hidden,
2002-02-04 22:33:09 +00:00
frame.y_hidden, frame.width, frame.height);
2001-12-11 20:47:02 +00:00
else
XMoveResizeWindow(display, frame.window, frame.x,
2002-02-04 22:33:09 +00:00
frame.y, frame.width, frame.height);
2001-12-11 20:47:02 +00:00
}
2002-08-14 21:51:07 +00:00
void Slit::shutdown() {
2002-05-29 06:21:59 +00:00
saveClientList();
2002-02-04 22:33:09 +00:00
while (clientList.size() != 0)
2002-05-29 06:21:59 +00:00
removeClient(clientList.front(), true, true);
2001-12-11 20:47:02 +00:00
}
void Slit::buttonPressEvent(XButtonEvent *e) {
if (e->window != frame.window) return;
if (e->button == Button1 && (! on_top)) {
2002-09-08 19:48:03 +00:00
Workspace::Stack st;
st.push_back(frame.window);
screen->raiseWindows(st);
2001-12-11 20:47:02 +00:00
} else if (e->button == Button2 && (! on_top)) {
XLowerWindow(display, frame.window);
} else if (e->button == Button3) {
2002-03-19 00:07:00 +00:00
if (! slitmenu.isVisible()) {
2002-04-08 22:36:30 +00:00
int x = e->x_root - (slitmenu.width() / 2),
y = e->y_root - (slitmenu.height() / 2);
2001-12-11 20:47:02 +00:00
if (x < 0)
x = 0;
2002-04-08 22:36:30 +00:00
else if (x + slitmenu.width() > screen->getWidth())
x = screen->getWidth() - slitmenu.width();
2001-12-11 20:47:02 +00:00
if (y < 0)
y = 0;
2002-04-08 22:36:30 +00:00
else if (y + slitmenu.height() > screen->getHeight())
y = screen->getHeight() - slitmenu.height();
2001-12-11 20:47:02 +00:00
2002-03-19 00:07:00 +00:00
slitmenu.move(x, y);
slitmenu.show();
2001-12-11 20:47:02 +00:00
} else
2002-03-19 00:07:00 +00:00
slitmenu.hide();
2001-12-11 20:47:02 +00:00
}
}
void Slit::enterNotifyEvent(XCrossingEvent *) {
if (! do_auto_hide)
return;
if (hidden) {
2002-08-14 21:51:07 +00:00
if (! timer.isTiming())
timer.start();
2001-12-11 20:47:02 +00:00
} else {
2002-08-14 21:51:07 +00:00
if (timer.isTiming())
timer.stop();
2001-12-11 20:47:02 +00:00
}
}
void Slit::leaveNotifyEvent(XCrossingEvent *) {
if (! do_auto_hide)
return;
if (hidden) {
2002-08-14 21:51:07 +00:00
if (timer.isTiming())
timer.stop();
2002-03-19 00:07:00 +00:00
} else if (! slitmenu.isVisible()) {
2002-08-14 21:51:07 +00:00
if (! timer.isTiming())
timer.start();
2001-12-11 20:47:02 +00:00
}
}
void Slit::configureRequestEvent(XConfigureRequestEvent *e) {
fluxbox->grab();
if (fluxbox->validateWindow(e->window)) {
2002-02-04 22:33:09 +00:00
bool reconf = false;
2001-12-11 20:47:02 +00:00
XWindowChanges xwc;
xwc.x = e->x;
xwc.y = e->y;
xwc.width = e->width;
xwc.height = e->height;
xwc.border_width = 0;
xwc.sibling = e->above;
xwc.stack_mode = e->detail;
XConfigureWindow(display, e->window, e->value_mask, &xwc);
2002-02-04 22:33:09 +00:00
SlitClients::iterator it = clientList.begin();
SlitClients::iterator it_end = clientList.end();
for (; it != it_end; ++it)
if ((*it)->window == e->window)
if ((*it)->width != ((unsigned) e->width) ||
(*it)->height != ((unsigned) e->height)) {
(*it)->width = (unsigned) e->width;
(*it)->height = (unsigned) e->height;
2001-12-11 20:47:02 +00:00
2002-02-04 22:33:09 +00:00
reconf = true;
2001-12-11 20:47:02 +00:00
break;
}
if (reconf) reconfigure();
}
fluxbox->ungrab();
}
2002-08-14 21:51:07 +00:00
void Slit::timeout() {
2001-12-11 20:47:02 +00:00
hidden = ! hidden;
if (hidden)
XMoveWindow(display, frame.window, frame.x_hidden, frame.y_hidden);
else
XMoveWindow(display, frame.window, frame.x, frame.y);
}
2002-08-14 21:51:07 +00:00
void Slit::loadClientList() {
2002-05-29 06:21:59 +00:00
const std::string &filename = fluxbox->getSlitlistFilename();
struct stat buf;
2002-08-14 21:51:07 +00:00
if (!stat(filename.c_str(), &buf)) {
2002-05-29 06:21:59 +00:00
std::ifstream file(fluxbox->getSlitlistFilename().c_str());
std::string name;
while (! file.eof()) {
name = "";
std::getline(file, name); // get the entire line
2002-05-29 06:21:59 +00:00
if (name.size() > 0) {
SlitClient *client = new SlitClient(name.c_str());
clientList.push_back(client);
}
}
}
}
void Slit::saveClientList(void) {
const std::string &filename = fluxbox->getSlitlistFilename();
std::ofstream file(filename.c_str());
SlitClients::iterator it = clientList.begin();
SlitClients::iterator it_end = clientList.end();
std::string prevName;
std::string name;
for (; it != it_end; ++it) {
name = (*it)->match_name;
if (name != prevName)
file << name.c_str() << std::endl;
2002-05-29 06:21:59 +00:00
prevName = name;
}
}
2001-12-11 20:47:02 +00:00
2002-05-08 14:12:28 +00:00
Slitmenu::Slitmenu(Slit &sl) : Basemenu(sl.screen),
slit(sl) {
2001-12-11 20:47:02 +00:00
I18n *i18n = I18n::instance();
using namespace FBNLS;
2001-12-11 20:47:02 +00:00
setLabel(i18n->getMessage(
SlitSet, SlitSlitTitle,
"Slit"));
2001-12-11 20:47:02 +00:00
setInternalMenu();
directionmenu = new Directionmenu(this);
placementmenu = new Placementmenu(this);
2002-03-19 14:30:43 +00:00
#ifdef XINERAMA
2002-05-08 14:12:28 +00:00
if (screen()->hasXinerama()) { // only create if we need
2002-03-19 14:30:43 +00:00
headmenu = new Headmenu(this);
}
#endif // XINERAMA
2001-12-11 20:47:02 +00:00
insert(i18n->getMessage(
CommonSet, CommonDirectionTitle,
"Direction"),
2001-12-11 20:47:02 +00:00
directionmenu);
insert(i18n->getMessage(
CommonSet, CommonPlacementTitle,
"Placement"),
2001-12-11 20:47:02 +00:00
placementmenu);
2002-03-19 14:30:43 +00:00
#ifdef XINERAMA
//TODO: NLS
2002-05-08 14:12:28 +00:00
if (screen()->hasXinerama()) {
2002-03-19 14:30:43 +00:00
insert(i18n->getMessage(0, 0, "Place on Head"), headmenu);
}
#endif // XINERAMA
2001-12-11 20:47:02 +00:00
insert(i18n->getMessage(
CommonSet, CommonAlwaysOnTop,
"Always on top"), 1);
2001-12-11 20:47:02 +00:00
insert(i18n->getMessage(
CommonSet, CommonAutoHide,
"Auto hide"), 2);
2001-12-11 20:47:02 +00:00
2002-05-08 14:12:28 +00:00
setItemSelected(2, slit.isOnTop());
setItemSelected(3, slit.doAutoHide());
2001-12-11 20:47:02 +00:00
update();
}
2002-08-14 21:51:07 +00:00
Slitmenu::~Slitmenu() {
2001-12-11 20:47:02 +00:00
delete directionmenu;
delete placementmenu;
2002-03-19 14:30:43 +00:00
#ifdef XINERAMA
2002-05-08 14:12:28 +00:00
if (screen()->hasXinerama()) {
2002-03-19 14:30:43 +00:00
delete headmenu;
}
#endif // XINERAMA
2001-12-11 20:47:02 +00:00
}
2002-04-03 12:08:54 +00:00
void Slitmenu::itemSelected(int button, unsigned int index) {
2001-12-11 20:47:02 +00:00
if (button == 1) {
BasemenuItem *item = find(index);
if (! item) return;
switch (item->function()) {
case 1: // always on top
2002-04-03 12:08:54 +00:00
{
2002-05-08 14:12:28 +00:00
bool change = ((slit.isOnTop()) ? false : true);
slit.on_top = change;
screen()->saveSlitOnTop(change);
2002-04-03 12:08:54 +00:00
setItemSelected(2, change);
2002-05-08 14:12:28 +00:00
if (slit.isOnTop())
2002-09-08 19:48:03 +00:00
screen()->raiseWindows(Workspace::Stack());
2002-05-08 14:12:28 +00:00
2002-04-03 12:08:54 +00:00
break;
}
2001-12-11 20:47:02 +00:00
case 2: // auto hide
2002-04-03 12:08:54 +00:00
{
2002-05-08 14:12:28 +00:00
bool change = (slit.doAutoHide() ? false : true);
slit.do_auto_hide = change;
screen()->saveSlitAutoHide(change);
2002-04-03 12:08:54 +00:00
setItemSelected(3, change);
break;
}
2001-12-11 20:47:02 +00:00
}
2002-05-08 14:12:28 +00:00
//save the new configuration
Fluxbox::instance()->save_rc();
update();
2001-12-11 20:47:02 +00:00
}
}
void Slitmenu::internal_hide(void) {
Basemenu::internal_hide();
2002-05-08 14:12:28 +00:00
if (slit.doAutoHide())
slit.timeout();
2001-12-11 20:47:02 +00:00
}
void Slitmenu::reconfigure(void) {
directionmenu->reconfigure();
placementmenu->reconfigure();
2002-03-19 14:30:43 +00:00
#ifdef XINERAMA
2002-05-08 14:12:28 +00:00
if (screen()->hasXinerama()) {
2002-03-19 14:30:43 +00:00
headmenu->reconfigure();
}
#endif // XINERAMA
2002-05-08 14:12:28 +00:00
setItemSelected(2, slit.isOnTop());
setItemSelected(3, slit.doAutoHide());
2001-12-11 20:47:02 +00:00
Basemenu::reconfigure();
}
2002-05-08 14:12:28 +00:00
Slitmenu::Directionmenu::Directionmenu(Slitmenu *sm) : Basemenu(sm->screen()),
slitmenu(sm) {
2001-12-11 20:47:02 +00:00
I18n *i18n = I18n::instance();
using namespace FBNLS;
2001-12-11 20:47:02 +00:00
setLabel(i18n->getMessage(
SlitSet, SlitSlitDirection,
"Slit Direction"));
2001-12-11 20:47:02 +00:00
setInternalMenu();
insert(i18n->getMessage(
CommonSet, CommonDirectionHoriz,
"Horizontal"),
2002-01-11 10:21:44 +00:00
Slit::HORIZONTAL);
2001-12-11 20:47:02 +00:00
insert(i18n->getMessage(
CommonSet, CommonDirectionVert,
"Vertical"),
2002-01-11 10:21:44 +00:00
Slit::VERTICAL);
2001-12-11 20:47:02 +00:00
update();
2002-05-08 14:12:28 +00:00
if (screen()->getSlitDirection() == Slit::HORIZONTAL)
2002-04-03 12:08:54 +00:00
setItemSelected(0, true);
2001-12-11 20:47:02 +00:00
else
2002-04-03 12:08:54 +00:00
setItemSelected(1, true);
2001-12-11 20:47:02 +00:00
}
2002-04-03 12:08:54 +00:00
void Slitmenu::Directionmenu::itemSelected(int button, unsigned int index) {
2001-12-11 20:47:02 +00:00
if (button == 1) {
BasemenuItem *item = find(index);
if (! item) return;
2002-05-08 14:12:28 +00:00
screen()->saveSlitDirection(item->function());
2001-12-11 20:47:02 +00:00
2002-01-11 10:21:44 +00:00
if (item->function() == Slit::HORIZONTAL) {
2002-04-03 12:08:54 +00:00
setItemSelected(0, true);
setItemSelected(1, false);
2001-12-11 20:47:02 +00:00
} else {
2002-04-03 12:08:54 +00:00
setItemSelected(0, false);
setItemSelected(1, true);
2001-12-11 20:47:02 +00:00
}
2002-05-08 14:12:28 +00:00
Fluxbox::instance()->save_rc();
hide();
slitmenu->slit.reconfigure();
2001-12-11 20:47:02 +00:00
}
}
2002-05-08 14:12:28 +00:00
Slitmenu::Placementmenu::Placementmenu(Slitmenu *sm) : Basemenu(sm->screen()),
slitmenu(sm) {
2001-12-11 20:47:02 +00:00
I18n *i18n = I18n::instance();
using namespace FBNLS;
2001-12-11 20:47:02 +00:00
setLabel(i18n->getMessage(
SlitSet, SlitSlitPlacement,
"Slit Placement"));
2001-12-11 20:47:02 +00:00
setMinimumSublevels(3);
setInternalMenu();
insert(i18n->getMessage(
CommonSet, CommonPlacementTopLeft,
"Top Left"),
2002-01-11 10:21:44 +00:00
Slit::TOPLEFT);
2001-12-11 20:47:02 +00:00
insert(i18n->getMessage(
CommonSet, CommonPlacementCenterLeft,
"Center Left"),
2002-01-11 10:21:44 +00:00
Slit::CENTERLEFT);
2001-12-11 20:47:02 +00:00
insert(i18n->getMessage(
CommonSet, CommonPlacementBottomLeft,
"Bottom Left"),
2002-01-11 10:21:44 +00:00
Slit::BOTTOMLEFT);
2001-12-11 20:47:02 +00:00
insert(i18n->getMessage(
CommonSet, CommonPlacementTopCenter,
"Top Center"),
2002-01-11 10:21:44 +00:00
Slit::TOPCENTER);
2001-12-11 20:47:02 +00:00
insert("");
insert(i18n->getMessage(
CommonSet, CommonPlacementBottomCenter,
"Bottom Center"),
2002-01-11 10:21:44 +00:00
Slit::BOTTOMCENTER);
2001-12-11 20:47:02 +00:00
insert(i18n->getMessage(
CommonSet, CommonPlacementTopRight,
"Top Right"),
2002-01-11 10:21:44 +00:00
Slit::TOPRIGHT);
2001-12-11 20:47:02 +00:00
insert(i18n->getMessage(
CommonSet, CommonPlacementCenterRight,
"Center Right"),
2002-01-11 10:21:44 +00:00
Slit::CENTERRIGHT);
2001-12-11 20:47:02 +00:00
insert(i18n->getMessage(
CommonSet, CommonPlacementBottomRight,
"Bottom Right"),
2002-01-11 10:21:44 +00:00
Slit::BOTTOMRIGHT);
2001-12-11 20:47:02 +00:00
update();
}
2002-04-03 12:08:54 +00:00
void Slitmenu::Placementmenu::itemSelected(int button, unsigned int index) {
2001-12-11 20:47:02 +00:00
if (button == 1) {
BasemenuItem *item = find(index);
if (! item) return;
if (item->function()) {
2002-05-08 14:12:28 +00:00
screen()->saveSlitPlacement(item->function());
2001-12-11 20:47:02 +00:00
hide();
2002-05-08 14:12:28 +00:00
slitmenu->slit.reconfigure();
Fluxbox::instance()->save_rc();
2001-12-11 20:47:02 +00:00
}
}
}
2002-03-19 14:30:43 +00:00
#ifdef XINERAMA
2002-05-08 14:12:28 +00:00
Slitmenu::Headmenu::Headmenu(Slitmenu *sm): Basemenu(sm->screen()),
slitmenu(sm) {
2002-03-19 14:30:43 +00:00
I18n *i18n = I18n::instance();
setLabel(i18n->getMessage(0, 0, "Place on Head")); //TODO: NLS
setInternalMenu();
2002-05-08 14:12:28 +00:00
int numHeads = screen()->getNumHeads();
2002-03-19 14:30:43 +00:00
// fill menu with head entries
for (int i = 0; i < numHeads; i++) {
char headName[32];
sprintf(headName, "Head %i", i+1); //TODO: NLS
insert(i18n->getMessage(0, 0, headName), i);
}
update();
}
2002-04-08 18:58:47 +00:00
void Slitmenu::Headmenu::itemSelected(int button, unsigned int index) {
2002-03-19 14:30:43 +00:00
if (button == 1) {
BasemenuItem *item = find(index);
if (! item)
return;
2002-05-08 14:12:28 +00:00
screen()->saveSlitOnHead(item->function());
2002-03-19 14:30:43 +00:00
hide();
2002-05-08 14:12:28 +00:00
slitmenu->slit.reconfigure();
Fluxbox::instance()->save_rc();
2002-03-19 14:30:43 +00:00
}
}
#endif // XINERAMA
2001-12-11 20:47:02 +00:00
2002-05-29 06:21:59 +00:00
Slit::SlitClient::SlitClient(const char *name)
{
initialize();
match_name = name;
}
Slit::SlitClient::SlitClient(BScreen *screen, Window w)
{
initialize(screen, w);
}
void Slit::SlitClient::initialize(BScreen *screen, Window w) {
client_window = w;
window = icon_window = None;
x = y = 0;
width = height = 0;
if (match_name.size() == 0)
getWMName(screen, client_window, match_name);
}
2001-12-11 20:47:02 +00:00
#endif // SLIT