2002-05-25 00:29:44 +00:00
|
|
|
// -*- mode: C++; indent-tabs-mode: nil; c-basic-offset: 2; -*-
|
|
|
|
// Window.cc for Blackbox - an X11 Window manager
|
|
|
|
// Copyright (c) 2001 - 2002 Sean 'Shaleh' Perry <shaleh at debian.org>
|
|
|
|
// Copyright (c) 1997 - 2000, 2002 Brad Hughes <bhughes at trolltech.com>
|
2002-04-11 03:20:38 +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.
|
|
|
|
|
|
|
|
#ifdef HAVE_CONFIG_H
|
|
|
|
# include "../config.h"
|
|
|
|
#endif // HAVE_CONFIG_H
|
|
|
|
|
2002-05-25 00:29:44 +00:00
|
|
|
extern "C" {
|
2002-04-11 03:20:38 +00:00
|
|
|
#include <X11/Xatom.h>
|
|
|
|
#include <X11/keysym.h>
|
|
|
|
|
2002-05-25 00:29:44 +00:00
|
|
|
#ifdef HAVE_STRING_H
|
2002-04-11 03:20:38 +00:00
|
|
|
# include <string.h>
|
2002-04-16 06:25:00 +00:00
|
|
|
#endif // HAVE_STRING_H
|
2002-04-11 03:20:38 +00:00
|
|
|
|
|
|
|
#ifdef DEBUG
|
|
|
|
# ifdef HAVE_STDIO_H
|
|
|
|
# include <stdio.h>
|
|
|
|
# endif // HAVE_STDIO_H
|
|
|
|
#endif // DEBUG
|
2002-05-25 00:29:44 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
#include <cstdlib>
|
|
|
|
|
|
|
|
#include "i18n.hh"
|
|
|
|
#include "blackbox.hh"
|
|
|
|
#include "GCCache.hh"
|
|
|
|
#include "Iconmenu.hh"
|
|
|
|
#include "Image.hh"
|
|
|
|
#include "Screen.hh"
|
|
|
|
#include "Toolbar.hh"
|
|
|
|
#include "Util.hh"
|
|
|
|
#include "Window.hh"
|
|
|
|
#include "Windowmenu.hh"
|
|
|
|
#include "Workspace.hh"
|
|
|
|
#include "Slit.hh"
|
2002-06-29 23:50:04 +00:00
|
|
|
#include "XAtom.hh"
|
|
|
|
#include "Input.hh"
|
2002-04-11 03:20:38 +00:00
|
|
|
|
2002-05-27 03:12:21 +00:00
|
|
|
using std::string;
|
2002-04-11 03:20:38 +00:00
|
|
|
|
|
|
|
/*
|
|
|
|
* Initializes the class with default values/the window's set initial values.
|
|
|
|
*/
|
2002-05-25 00:29:44 +00:00
|
|
|
BlackboxWindow::BlackboxWindow(Blackbox *b, Window w, BScreen *s) {
|
|
|
|
// fprintf(stderr, "BlackboxWindow size: %d bytes\n",
|
|
|
|
// sizeof(BlackboxWindow));
|
|
|
|
|
2002-04-11 03:20:38 +00:00
|
|
|
#ifdef DEBUG
|
2002-05-25 00:29:44 +00:00
|
|
|
fprintf(stderr, "BlackboxWindow::BlackboxWindow(): creating 0x%lx\n", w);
|
2002-04-11 03:20:38 +00:00
|
|
|
#endif // DEBUG
|
|
|
|
|
2002-06-21 01:06:29 +00:00
|
|
|
/*
|
|
|
|
set timer to zero... it is initialized properly later, so we check
|
|
|
|
if timer is zero in the destructor, and assume that the window is not
|
|
|
|
fully constructed if timer is zero...
|
|
|
|
*/
|
2002-05-25 00:29:44 +00:00
|
|
|
timer = 0;
|
|
|
|
blackbox = b;
|
2002-04-11 03:20:38 +00:00
|
|
|
client.window = w;
|
2002-05-25 00:29:44 +00:00
|
|
|
screen = s;
|
2002-05-30 06:51:43 +00:00
|
|
|
xatom = blackbox->getXAtom();
|
2002-06-29 23:50:04 +00:00
|
|
|
input = blackbox->getInput();
|
2002-05-25 00:29:44 +00:00
|
|
|
|
|
|
|
if (! validateClient()) {
|
|
|
|
delete this;
|
|
|
|
return;
|
|
|
|
}
|
2002-04-11 03:20:38 +00:00
|
|
|
|
2002-05-25 00:29:44 +00:00
|
|
|
// set the eventmask early in the game so that we make sure we get
|
|
|
|
// all the events we are interested in
|
|
|
|
XSetWindowAttributes attrib_set;
|
|
|
|
attrib_set.event_mask = PropertyChangeMask | FocusChangeMask |
|
|
|
|
StructureNotifyMask;
|
|
|
|
attrib_set.do_not_propagate_mask = ButtonPressMask | ButtonReleaseMask |
|
|
|
|
ButtonMotionMask;
|
|
|
|
XChangeWindowAttributes(blackbox->getXDisplay(), client.window,
|
|
|
|
CWEventMask|CWDontPropagate, &attrib_set);
|
2002-04-11 03:20:38 +00:00
|
|
|
|
|
|
|
// fetch client size and placement
|
|
|
|
XWindowAttributes wattrib;
|
2002-05-25 00:29:44 +00:00
|
|
|
if ((! XGetWindowAttributes(blackbox->getXDisplay(),
|
|
|
|
client.window, &wattrib)) ||
|
2002-04-11 03:20:38 +00:00
|
|
|
(! wattrib.screen) || wattrib.override_redirect) {
|
|
|
|
#ifdef DEBUG
|
|
|
|
fprintf(stderr,
|
2002-05-25 00:29:44 +00:00
|
|
|
"BlackboxWindow::BlackboxWindow(): XGetWindowAttributes failed\n");
|
2002-04-11 03:20:38 +00:00
|
|
|
#endif // DEBUG
|
|
|
|
|
2002-05-25 00:29:44 +00:00
|
|
|
delete this;
|
2002-04-11 03:20:38 +00:00
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
flags.moving = flags.resizing = flags.shaded = flags.visible =
|
2002-05-25 00:29:44 +00:00
|
|
|
flags.iconic = flags.focused = flags.stuck = flags.modal =
|
2002-06-21 20:40:14 +00:00
|
|
|
flags.send_focus_message = flags.shaped = flags.skip_taskbar =
|
|
|
|
flags.skip_pager = flags.fullscreen = False;
|
2002-04-11 03:20:38 +00:00
|
|
|
flags.maximized = 0;
|
|
|
|
|
2002-05-25 00:29:44 +00:00
|
|
|
blackbox_attrib.workspace = window_number = BSENTINEL;
|
2002-04-11 03:20:38 +00:00
|
|
|
|
2002-05-25 00:29:44 +00:00
|
|
|
blackbox_attrib.flags = blackbox_attrib.attrib = blackbox_attrib.stack
|
|
|
|
= blackbox_attrib.decoration = 0l;
|
|
|
|
blackbox_attrib.premax_x = blackbox_attrib.premax_y = 0;
|
|
|
|
blackbox_attrib.premax_w = blackbox_attrib.premax_h = 0;
|
2002-04-11 03:20:38 +00:00
|
|
|
|
2002-05-25 00:29:44 +00:00
|
|
|
frame.border_w = 1;
|
2002-04-11 03:20:38 +00:00
|
|
|
frame.window = frame.plate = frame.title = frame.handle = None;
|
|
|
|
frame.close_button = frame.iconify_button = frame.maximize_button = None;
|
|
|
|
frame.right_grip = frame.left_grip = None;
|
|
|
|
|
2002-05-25 00:29:44 +00:00
|
|
|
frame.ulabel_pixel = frame.flabel_pixel = frame.utitle_pixel =
|
|
|
|
frame.ftitle_pixel = frame.uhandle_pixel = frame.fhandle_pixel =
|
|
|
|
frame.ubutton_pixel = frame.fbutton_pixel = frame.pbutton_pixel =
|
|
|
|
frame.uborder_pixel = frame.fborder_pixel = frame.ugrip_pixel =
|
|
|
|
frame.fgrip_pixel = 0;
|
2002-04-11 03:20:38 +00:00
|
|
|
frame.utitle = frame.ftitle = frame.uhandle = frame.fhandle = None;
|
|
|
|
frame.ulabel = frame.flabel = frame.ubutton = frame.fbutton = None;
|
2002-05-25 00:29:44 +00:00
|
|
|
frame.pbutton = frame.ugrip = frame.fgrip = decorations;
|
2002-04-11 03:20:38 +00:00
|
|
|
|
2002-05-25 00:29:44 +00:00
|
|
|
decorations = Decor_Titlebar | Decor_Border | Decor_Handle |
|
|
|
|
Decor_Iconify | Decor_Maximize;
|
|
|
|
functions = Func_Resize | Func_Move | Func_Iconify | Func_Maximize;
|
2002-04-11 03:20:38 +00:00
|
|
|
|
|
|
|
client.wm_hint_flags = client.normal_hint_flags = 0;
|
2002-05-25 00:29:44 +00:00
|
|
|
client.transient_for = 0;
|
2002-04-11 03:20:38 +00:00
|
|
|
|
2002-06-21 01:06:29 +00:00
|
|
|
/*
|
|
|
|
get the initial size and location of client window (relative to the
|
|
|
|
_root window_). This position is the reference point used with the
|
|
|
|
window's gravity to find the window's initial position.
|
|
|
|
*/
|
2002-05-25 00:29:44 +00:00
|
|
|
client.rect.setRect(wattrib.x, wattrib.y, wattrib.width, wattrib.height);
|
2002-04-11 03:20:38 +00:00
|
|
|
client.old_bw = wattrib.border_width;
|
|
|
|
|
|
|
|
windowmenu = 0;
|
|
|
|
lastButtonPressTime = 0;
|
|
|
|
|
2002-05-25 00:29:44 +00:00
|
|
|
timer = new BTimer(blackbox, this);
|
|
|
|
timer->setTimeout(blackbox->getAutoRaiseDelay());
|
2002-04-11 03:20:38 +00:00
|
|
|
|
2002-06-21 20:40:14 +00:00
|
|
|
if (! getBlackboxHints()) {
|
2002-04-11 03:20:38 +00:00
|
|
|
getMWMHints();
|
2002-06-21 20:40:14 +00:00
|
|
|
getNetWMHints();
|
|
|
|
}
|
2002-04-11 03:20:38 +00:00
|
|
|
|
|
|
|
// get size, aspect, minimum/maximum size and other hints set by the
|
|
|
|
// client
|
|
|
|
getWMProtocols();
|
|
|
|
getWMHints();
|
|
|
|
getWMNormalHints();
|
|
|
|
|
|
|
|
if (client.initial_state == WithdrawnState) {
|
|
|
|
screen->getSlit()->addClient(client.window);
|
2002-04-18 20:56:23 +00:00
|
|
|
delete this;
|
2002-04-11 03:20:38 +00:00
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
2002-06-21 20:40:14 +00:00
|
|
|
if (isKDESystrayWindow()) {
|
|
|
|
screen->addSystrayWindow(client.window);
|
|
|
|
delete this;
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
2002-05-25 00:29:44 +00:00
|
|
|
frame.window = createToplevelWindow();
|
|
|
|
frame.plate = createChildWindow(frame.window);
|
|
|
|
associateClientWindow();
|
2002-04-11 03:20:38 +00:00
|
|
|
|
2002-05-25 00:29:44 +00:00
|
|
|
blackbox->saveWindowSearch(frame.window, this);
|
|
|
|
blackbox->saveWindowSearch(frame.plate, this);
|
|
|
|
blackbox->saveWindowSearch(client.window, this);
|
2002-04-11 03:20:38 +00:00
|
|
|
|
2002-06-21 20:40:14 +00:00
|
|
|
screen->addStrut(&client.strut);
|
|
|
|
updateStrut();
|
|
|
|
|
2002-05-25 00:29:44 +00:00
|
|
|
// determine if this is a transient window
|
|
|
|
getTransientInfo();
|
2002-04-11 03:20:38 +00:00
|
|
|
|
2002-06-21 20:40:14 +00:00
|
|
|
// determine the window's type, so we can decide its decorations and
|
|
|
|
// functionality, or if we should not manage it at all
|
|
|
|
getWindowType();
|
|
|
|
|
|
|
|
// adjust the window decorations/behavior based on the window type
|
|
|
|
switch (window_type) {
|
|
|
|
case Type_Desktop:
|
|
|
|
// desktop windows are not managed by us, we just make sure they stay on the
|
|
|
|
// bottom.
|
|
|
|
return;
|
|
|
|
|
|
|
|
case Type_Dock:
|
|
|
|
// docks (such as kicker) cannot be moved, and appear on all workspaces
|
|
|
|
functions &= ~(Func_Move);
|
|
|
|
flags.stuck = True;
|
|
|
|
case Type_Toolbar:
|
|
|
|
case Type_Menu:
|
|
|
|
case Type_Utility:
|
|
|
|
// these windows have minimal decorations, only a titlebar, and cannot
|
|
|
|
// be resized or iconified
|
|
|
|
decorations &= ~(Decor_Maximize | Decor_Handle | Decor_Border |
|
|
|
|
Decor_Iconify);
|
|
|
|
functions &= ~(Func_Resize | Func_Maximize | Func_Iconify);
|
|
|
|
break;
|
|
|
|
|
|
|
|
case Type_Splash:
|
|
|
|
// splash screens have no functionality or decorations, they are left up
|
|
|
|
// to the application which created them
|
|
|
|
decorations = 0;
|
|
|
|
functions = 0;
|
|
|
|
break;
|
|
|
|
|
|
|
|
case Type_Dialog:
|
|
|
|
// dialogs cannot be maximized, and don't display a handle
|
2002-05-25 00:29:44 +00:00
|
|
|
decorations &= ~(Decor_Maximize | Decor_Handle);
|
|
|
|
functions &= ~Func_Maximize;
|
2002-06-21 20:40:14 +00:00
|
|
|
break;
|
|
|
|
|
|
|
|
case Type_Normal:
|
|
|
|
// normal windows retain all of the possible decorations and functionality
|
|
|
|
break;
|
2002-05-25 00:29:44 +00:00
|
|
|
}
|
2002-04-11 03:20:38 +00:00
|
|
|
|
2002-06-21 20:40:14 +00:00
|
|
|
// further adjeust the window's decorations/behavior based on window sizes
|
2002-04-11 03:20:38 +00:00
|
|
|
if ((client.normal_hint_flags & PMinSize) &&
|
|
|
|
(client.normal_hint_flags & PMaxSize) &&
|
2002-05-16 22:35:59 +00:00
|
|
|
client.max_width <= client.min_width &&
|
2002-04-11 03:20:38 +00:00
|
|
|
client.max_height <= client.min_height) {
|
2002-05-25 00:29:44 +00:00
|
|
|
decorations &= ~(Decor_Maximize | Decor_Handle);
|
|
|
|
functions &= ~(Func_Resize | Func_Maximize);
|
2002-04-11 03:20:38 +00:00
|
|
|
}
|
|
|
|
upsize();
|
|
|
|
|
2002-06-21 20:40:14 +00:00
|
|
|
setAllowedActions();
|
|
|
|
|
2002-05-25 00:29:44 +00:00
|
|
|
bool place_window = True;
|
|
|
|
if (blackbox->isStartup() || isTransient() ||
|
2002-04-11 03:20:38 +00:00
|
|
|
client.normal_hint_flags & (PPosition|USPosition)) {
|
|
|
|
setGravityOffsets();
|
|
|
|
|
|
|
|
|
2002-05-25 00:29:44 +00:00
|
|
|
if (blackbox->isStartup() ||
|
|
|
|
client.rect.intersects(screen->availableArea()))
|
|
|
|
place_window = False;
|
2002-04-11 03:20:38 +00:00
|
|
|
}
|
|
|
|
|
2002-05-25 00:29:44 +00:00
|
|
|
if (decorations & Decor_Titlebar)
|
|
|
|
createTitlebar();
|
2002-04-11 03:20:38 +00:00
|
|
|
|
2002-05-25 00:29:44 +00:00
|
|
|
if (decorations & Decor_Handle)
|
|
|
|
createHandle();
|
2002-04-11 03:20:38 +00:00
|
|
|
|
2002-05-25 00:29:44 +00:00
|
|
|
#ifdef SHAPE
|
|
|
|
if (blackbox->hasShapeExtensions() && flags.shaped) {
|
|
|
|
configureShape();
|
2002-04-11 03:20:38 +00:00
|
|
|
}
|
2002-05-25 00:29:44 +00:00
|
|
|
#endif // SHAPE
|
2002-04-11 03:20:38 +00:00
|
|
|
|
2002-06-29 23:50:04 +00:00
|
|
|
grabButtons();
|
2002-04-11 03:20:38 +00:00
|
|
|
|
|
|
|
positionWindows();
|
2002-05-25 00:29:44 +00:00
|
|
|
decorate();
|
2002-04-11 03:20:38 +00:00
|
|
|
|
2002-05-25 00:29:44 +00:00
|
|
|
if (decorations & Decor_Titlebar)
|
|
|
|
XMapSubwindows(blackbox->getXDisplay(), frame.title);
|
|
|
|
XMapSubwindows(blackbox->getXDisplay(), frame.window);
|
2002-04-11 03:20:38 +00:00
|
|
|
|
2002-05-25 00:29:44 +00:00
|
|
|
windowmenu = new Windowmenu(this);
|
2002-04-11 03:20:38 +00:00
|
|
|
|
2002-05-25 00:29:44 +00:00
|
|
|
if (blackbox_attrib.workspace >= screen->getWorkspaceCount())
|
2002-04-11 03:20:38 +00:00
|
|
|
screen->getCurrentWorkspace()->addWindow(this, place_window);
|
|
|
|
else
|
2002-05-25 00:29:44 +00:00
|
|
|
screen->getWorkspace(blackbox_attrib.workspace)->
|
|
|
|
addWindow(this, place_window);
|
2002-04-11 03:20:38 +00:00
|
|
|
|
2002-05-25 00:29:44 +00:00
|
|
|
if (! place_window) {
|
|
|
|
// don't need to call configure if we are letting the workspace
|
|
|
|
// place the window
|
|
|
|
configure(frame.rect.x(), frame.rect.y(),
|
|
|
|
frame.rect.width(), frame.rect.height());
|
|
|
|
}
|
2002-04-11 03:20:38 +00:00
|
|
|
|
2002-06-21 01:06:29 +00:00
|
|
|
// preserve the window's initial state on first map, and its current state
|
|
|
|
// across a restart
|
|
|
|
if (! getState()) {
|
|
|
|
if (client.wm_hint_flags & StateHint)
|
|
|
|
current_state = client.initial_state;
|
|
|
|
else
|
|
|
|
current_state = NormalState;
|
|
|
|
}
|
|
|
|
|
2002-06-21 20:40:14 +00:00
|
|
|
// get sticky state from our parent window if we've got one
|
|
|
|
if (isTransient() && client.transient_for != (BlackboxWindow *) ~0ul &&
|
|
|
|
client.transient_for->isStuck() != flags.stuck)
|
|
|
|
stick();
|
|
|
|
|
2002-04-11 03:20:38 +00:00
|
|
|
if (flags.shaded) {
|
|
|
|
flags.shaded = False;
|
|
|
|
shade();
|
2002-06-21 01:06:29 +00:00
|
|
|
|
|
|
|
/*
|
|
|
|
Because the iconic'ness of shaded windows is lost, we need to set the
|
|
|
|
state to NormalState so that shaded windows on other workspaces will not
|
|
|
|
get shown on the first workspace.
|
|
|
|
At this point in the life of a window, current_state should only be set
|
|
|
|
to IconicState if the window was an *icon*, not if it was shaded.
|
|
|
|
*/
|
|
|
|
current_state = NormalState;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (flags.stuck) {
|
|
|
|
flags.stuck = False;
|
|
|
|
stick();
|
2002-04-11 03:20:38 +00:00
|
|
|
}
|
|
|
|
|
2002-05-25 00:29:44 +00:00
|
|
|
if (flags.maximized && (functions & Func_Maximize)) {
|
|
|
|
remaximize();
|
2002-04-11 03:20:38 +00:00
|
|
|
}
|
|
|
|
|
2002-06-21 01:06:29 +00:00
|
|
|
/*
|
|
|
|
When the window is mapped (and also when its attributes are restored), the
|
|
|
|
current_state that was set here will be used.
|
|
|
|
It is set to Normal if the window is to be mapped or it is set to Iconic
|
|
|
|
if the window is to be iconified.
|
|
|
|
*Note* that for sticky windows, the same rules apply here, they are in
|
|
|
|
fact never set to Iconic since there is no way for us to tell if a sticky
|
|
|
|
window was iconified previously.
|
|
|
|
*/
|
|
|
|
|
2002-04-11 03:20:38 +00:00
|
|
|
setFocusFlag(False);
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2002-05-25 00:29:44 +00:00
|
|
|
BlackboxWindow::~BlackboxWindow(void) {
|
|
|
|
#ifdef DEBUG
|
|
|
|
fprintf(stderr, "BlackboxWindow::~BlackboxWindow: destroying 0x%lx\n",
|
|
|
|
client.window);
|
|
|
|
#endif // DEBUG
|
2002-04-11 03:20:38 +00:00
|
|
|
|
2002-05-25 00:29:44 +00:00
|
|
|
if (! timer) // window not managed...
|
|
|
|
return;
|
2002-04-11 03:20:38 +00:00
|
|
|
|
2002-06-21 20:40:14 +00:00
|
|
|
screen->removeStrut(&client.strut);
|
|
|
|
screen->updateAvailableArea();
|
|
|
|
|
|
|
|
// We don't need to worry about resizing because resizing always grabs the X
|
|
|
|
// server. This should only ever happen if using opaque moving.
|
|
|
|
if (flags.moving)
|
|
|
|
endMove();
|
2002-04-11 03:20:38 +00:00
|
|
|
|
2002-05-25 00:29:44 +00:00
|
|
|
delete timer;
|
2002-04-11 03:20:38 +00:00
|
|
|
|
2002-05-25 00:29:44 +00:00
|
|
|
delete windowmenu;
|
2002-04-11 03:20:38 +00:00
|
|
|
|
2002-05-25 00:29:44 +00:00
|
|
|
if (client.window_group) {
|
|
|
|
BWindowGroup *group = blackbox->searchGroup(client.window_group);
|
|
|
|
if (group) group->removeWindow(this);
|
2002-04-11 03:20:38 +00:00
|
|
|
}
|
|
|
|
|
2002-05-25 00:29:44 +00:00
|
|
|
// remove ourselves from our transient_for
|
|
|
|
if (isTransient()) {
|
|
|
|
if (client.transient_for != (BlackboxWindow *) ~0ul) {
|
|
|
|
client.transient_for->client.transientList.remove(this);
|
|
|
|
}
|
|
|
|
client.transient_for = (BlackboxWindow*) 0;
|
2002-04-11 03:20:38 +00:00
|
|
|
}
|
|
|
|
|
2002-05-25 00:29:44 +00:00
|
|
|
if (client.transientList.size() > 0) {
|
|
|
|
// reset transient_for for all transients
|
|
|
|
BlackboxWindowList::iterator it, end = client.transientList.end();
|
|
|
|
for (it = client.transientList.begin(); it != end; ++it) {
|
|
|
|
(*it)->client.transient_for = (BlackboxWindow*) 0;
|
|
|
|
}
|
|
|
|
}
|
2002-04-11 03:20:38 +00:00
|
|
|
|
2002-05-25 00:29:44 +00:00
|
|
|
if (frame.title)
|
|
|
|
destroyTitlebar();
|
2002-04-11 03:20:38 +00:00
|
|
|
|
2002-05-25 00:29:44 +00:00
|
|
|
if (frame.handle)
|
|
|
|
destroyHandle();
|
2002-04-11 03:20:38 +00:00
|
|
|
|
|
|
|
if (frame.plate) {
|
2002-05-25 00:29:44 +00:00
|
|
|
blackbox->removeWindowSearch(frame.plate);
|
|
|
|
XDestroyWindow(blackbox->getXDisplay(), frame.plate);
|
2002-04-11 03:20:38 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
if (frame.window) {
|
2002-05-25 00:29:44 +00:00
|
|
|
blackbox->removeWindowSearch(frame.window);
|
|
|
|
XDestroyWindow(blackbox->getXDisplay(), frame.window);
|
2002-04-11 03:20:38 +00:00
|
|
|
}
|
|
|
|
|
2002-05-25 00:29:44 +00:00
|
|
|
blackbox->removeWindowSearch(client.window);
|
2002-04-11 03:20:38 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
/*
|
|
|
|
* Creates a new top level window, with a given location, size, and border
|
|
|
|
* width.
|
|
|
|
* Returns: the newly created window
|
|
|
|
*/
|
2002-05-25 00:29:44 +00:00
|
|
|
Window BlackboxWindow::createToplevelWindow(void) {
|
2002-04-11 03:20:38 +00:00
|
|
|
XSetWindowAttributes attrib_create;
|
|
|
|
unsigned long create_mask = CWBackPixmap | CWBorderPixel | CWColormap |
|
2002-05-25 00:29:44 +00:00
|
|
|
CWOverrideRedirect | CWEventMask;
|
2002-04-11 03:20:38 +00:00
|
|
|
|
|
|
|
attrib_create.background_pixmap = None;
|
|
|
|
attrib_create.colormap = screen->getColormap();
|
|
|
|
attrib_create.override_redirect = True;
|
|
|
|
attrib_create.event_mask = ButtonPressMask | ButtonReleaseMask |
|
2002-05-25 00:29:44 +00:00
|
|
|
ButtonMotionMask | EnterWindowMask;
|
2002-04-11 03:20:38 +00:00
|
|
|
|
2002-05-25 00:29:44 +00:00
|
|
|
return XCreateWindow(blackbox->getXDisplay(), screen->getRootWindow(),
|
|
|
|
-1, -1, 1, 1, frame.border_w, screen->getDepth(),
|
|
|
|
InputOutput, screen->getVisual(), create_mask,
|
2002-05-16 22:35:59 +00:00
|
|
|
&attrib_create);
|
2002-04-11 03:20:38 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
/*
|
|
|
|
* Creates a child window, and optionally associates a given cursor with
|
|
|
|
* the new window.
|
|
|
|
*/
|
2002-05-25 00:29:44 +00:00
|
|
|
Window BlackboxWindow::createChildWindow(Window parent, Cursor cursor) {
|
2002-04-11 03:20:38 +00:00
|
|
|
XSetWindowAttributes attrib_create;
|
|
|
|
unsigned long create_mask = CWBackPixmap | CWBorderPixel |
|
2002-05-25 00:29:44 +00:00
|
|
|
CWEventMask;
|
2002-04-11 03:20:38 +00:00
|
|
|
|
|
|
|
attrib_create.background_pixmap = None;
|
|
|
|
attrib_create.event_mask = ButtonPressMask | ButtonReleaseMask |
|
2002-05-25 00:29:44 +00:00
|
|
|
ButtonMotionMask | ExposureMask;
|
2002-04-11 03:20:38 +00:00
|
|
|
|
|
|
|
if (cursor) {
|
|
|
|
create_mask |= CWCursor;
|
|
|
|
attrib_create.cursor = cursor;
|
|
|
|
}
|
|
|
|
|
2002-05-25 00:29:44 +00:00
|
|
|
return XCreateWindow(blackbox->getXDisplay(), parent, 0, 0, 1, 1, 0,
|
|
|
|
screen->getDepth(), InputOutput, screen->getVisual(),
|
|
|
|
create_mask, &attrib_create);
|
2002-04-11 03:20:38 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
|
2002-05-25 00:29:44 +00:00
|
|
|
void BlackboxWindow::associateClientWindow(void) {
|
|
|
|
XSetWindowBorderWidth(blackbox->getXDisplay(), client.window, 0);
|
2002-04-11 03:20:38 +00:00
|
|
|
getWMName();
|
|
|
|
getWMIconName();
|
|
|
|
|
2002-05-25 00:29:44 +00:00
|
|
|
XChangeSaveSet(blackbox->getXDisplay(), client.window, SetModeInsert);
|
2002-04-11 03:20:38 +00:00
|
|
|
|
2002-05-25 00:29:44 +00:00
|
|
|
XSelectInput(blackbox->getXDisplay(), frame.plate, SubstructureRedirectMask);
|
2002-04-11 03:20:38 +00:00
|
|
|
|
2002-05-25 00:29:44 +00:00
|
|
|
XGrabServer(blackbox->getXDisplay());
|
|
|
|
XSelectInput(blackbox->getXDisplay(), client.window, NoEventMask);
|
|
|
|
XReparentWindow(blackbox->getXDisplay(), client.window, frame.plate, 0, 0);
|
|
|
|
XSelectInput(blackbox->getXDisplay(), client.window,
|
|
|
|
PropertyChangeMask | FocusChangeMask | StructureNotifyMask);
|
|
|
|
XUngrabServer(blackbox->getXDisplay());
|
2002-04-11 03:20:38 +00:00
|
|
|
|
2002-05-25 00:29:44 +00:00
|
|
|
XRaiseWindow(blackbox->getXDisplay(), frame.plate);
|
|
|
|
XMapSubwindows(blackbox->getXDisplay(), frame.plate);
|
2002-04-11 03:20:38 +00:00
|
|
|
|
|
|
|
|
|
|
|
#ifdef SHAPE
|
2002-05-25 00:29:44 +00:00
|
|
|
if (blackbox->hasShapeExtensions()) {
|
|
|
|
XShapeSelectInput(blackbox->getXDisplay(), client.window,
|
|
|
|
ShapeNotifyMask);
|
2002-04-11 03:20:38 +00:00
|
|
|
|
2002-05-25 00:29:44 +00:00
|
|
|
Bool shaped = False;
|
2002-04-11 03:20:38 +00:00
|
|
|
int foo;
|
|
|
|
unsigned int ufoo;
|
|
|
|
|
2002-05-25 00:29:44 +00:00
|
|
|
XShapeQueryExtents(blackbox->getXDisplay(), client.window, &shaped,
|
|
|
|
&foo, &foo, &ufoo, &ufoo, &foo, &foo, &foo,
|
|
|
|
&ufoo, &ufoo);
|
|
|
|
flags.shaped = shaped;
|
2002-04-11 03:20:38 +00:00
|
|
|
}
|
|
|
|
#endif // SHAPE
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2002-05-25 00:29:44 +00:00
|
|
|
void BlackboxWindow::decorate(void) {
|
|
|
|
BTexture* texture;
|
|
|
|
|
|
|
|
texture = &(screen->getWindowStyle()->b_focus);
|
|
|
|
frame.fbutton = texture->render(frame.button_w, frame.button_w,
|
|
|
|
frame.fbutton);
|
|
|
|
if (! frame.fbutton)
|
|
|
|
frame.fbutton_pixel = texture->color().pixel();
|
2002-04-11 03:20:38 +00:00
|
|
|
|
|
|
|
texture = &(screen->getWindowStyle()->b_unfocus);
|
2002-05-25 00:29:44 +00:00
|
|
|
frame.ubutton = texture->render(frame.button_w, frame.button_w,
|
|
|
|
frame.ubutton);
|
|
|
|
if (! frame.ubutton)
|
|
|
|
frame.ubutton_pixel = texture->color().pixel();
|
2002-04-11 03:20:38 +00:00
|
|
|
|
|
|
|
texture = &(screen->getWindowStyle()->b_pressed);
|
2002-05-25 00:29:44 +00:00
|
|
|
frame.pbutton = texture->render(frame.button_w, frame.button_w,
|
|
|
|
frame.pbutton);
|
|
|
|
if (! frame.pbutton)
|
|
|
|
frame.pbutton_pixel = texture->color().pixel();
|
2002-04-11 03:20:38 +00:00
|
|
|
|
2002-05-25 00:29:44 +00:00
|
|
|
if (decorations & Decor_Titlebar) {
|
2002-04-11 03:20:38 +00:00
|
|
|
texture = &(screen->getWindowStyle()->t_focus);
|
2002-05-25 00:29:44 +00:00
|
|
|
frame.ftitle = texture->render(frame.inside_w, frame.title_h,
|
|
|
|
frame.ftitle);
|
|
|
|
if (! frame.ftitle)
|
|
|
|
frame.ftitle_pixel = texture->color().pixel();
|
2002-04-11 03:20:38 +00:00
|
|
|
|
|
|
|
texture = &(screen->getWindowStyle()->t_unfocus);
|
2002-05-25 00:29:44 +00:00
|
|
|
frame.utitle = texture->render(frame.inside_w, frame.title_h,
|
|
|
|
frame.utitle);
|
|
|
|
if (! frame.utitle)
|
|
|
|
frame.utitle_pixel = texture->color().pixel();
|
2002-04-11 03:20:38 +00:00
|
|
|
|
2002-05-25 00:29:44 +00:00
|
|
|
XSetWindowBorder(blackbox->getXDisplay(), frame.title,
|
|
|
|
screen->getBorderColor()->pixel());
|
2002-04-11 03:20:38 +00:00
|
|
|
|
|
|
|
decorateLabel();
|
|
|
|
}
|
|
|
|
|
2002-05-25 00:29:44 +00:00
|
|
|
if (decorations & Decor_Border) {
|
|
|
|
frame.fborder_pixel = screen->getWindowStyle()->f_focus.pixel();
|
|
|
|
frame.uborder_pixel = screen->getWindowStyle()->f_unfocus.pixel();
|
|
|
|
blackbox_attrib.flags |= AttribDecoration;
|
|
|
|
blackbox_attrib.decoration = DecorNormal;
|
2002-04-11 03:20:38 +00:00
|
|
|
} else {
|
2002-05-25 00:29:44 +00:00
|
|
|
blackbox_attrib.flags |= AttribDecoration;
|
|
|
|
blackbox_attrib.decoration = DecorNone;
|
2002-04-11 03:20:38 +00:00
|
|
|
}
|
|
|
|
|
2002-05-25 00:29:44 +00:00
|
|
|
if (decorations & Decor_Handle) {
|
2002-04-11 03:20:38 +00:00
|
|
|
texture = &(screen->getWindowStyle()->h_focus);
|
2002-05-25 00:29:44 +00:00
|
|
|
frame.fhandle = texture->render(frame.inside_w, frame.handle_h,
|
|
|
|
frame.fhandle);
|
|
|
|
if (! frame.fhandle)
|
|
|
|
frame.fhandle_pixel = texture->color().pixel();
|
2002-04-11 03:20:38 +00:00
|
|
|
|
|
|
|
texture = &(screen->getWindowStyle()->h_unfocus);
|
2002-05-25 00:29:44 +00:00
|
|
|
frame.uhandle = texture->render(frame.inside_w, frame.handle_h,
|
|
|
|
frame.uhandle);
|
|
|
|
if (! frame.uhandle)
|
|
|
|
frame.uhandle_pixel = texture->color().pixel();
|
2002-04-11 03:20:38 +00:00
|
|
|
|
|
|
|
texture = &(screen->getWindowStyle()->g_focus);
|
2002-05-25 00:29:44 +00:00
|
|
|
frame.fgrip = texture->render(frame.grip_w, frame.handle_h, frame.fgrip);
|
|
|
|
if (! frame.fgrip)
|
|
|
|
frame.fgrip_pixel = texture->color().pixel();
|
2002-04-11 03:20:38 +00:00
|
|
|
|
|
|
|
texture = &(screen->getWindowStyle()->g_unfocus);
|
2002-05-25 00:29:44 +00:00
|
|
|
frame.ugrip = texture->render(frame.grip_w, frame.handle_h, frame.ugrip);
|
|
|
|
if (! frame.ugrip)
|
|
|
|
frame.ugrip_pixel = texture->color().pixel();
|
2002-04-11 03:20:38 +00:00
|
|
|
|
2002-05-25 00:29:44 +00:00
|
|
|
XSetWindowBorder(blackbox->getXDisplay(), frame.handle,
|
|
|
|
screen->getBorderColor()->pixel());
|
|
|
|
XSetWindowBorder(blackbox->getXDisplay(), frame.left_grip,
|
|
|
|
screen->getBorderColor()->pixel());
|
|
|
|
XSetWindowBorder(blackbox->getXDisplay(), frame.right_grip,
|
|
|
|
screen->getBorderColor()->pixel());
|
2002-04-11 03:20:38 +00:00
|
|
|
}
|
|
|
|
|
2002-05-25 00:29:44 +00:00
|
|
|
XSetWindowBorder(blackbox->getXDisplay(), frame.window,
|
|
|
|
screen->getBorderColor()->pixel());
|
2002-04-11 03:20:38 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
|
2002-05-25 00:29:44 +00:00
|
|
|
void BlackboxWindow::decorateLabel(void) {
|
|
|
|
BTexture *texture;
|
|
|
|
|
|
|
|
texture = &(screen->getWindowStyle()->l_focus);
|
|
|
|
frame.flabel = texture->render(frame.label_w, frame.label_h, frame.flabel);
|
|
|
|
if (! frame.flabel)
|
|
|
|
frame.flabel_pixel = texture->color().pixel();
|
2002-04-11 03:20:38 +00:00
|
|
|
|
|
|
|
texture = &(screen->getWindowStyle()->l_unfocus);
|
2002-05-25 00:29:44 +00:00
|
|
|
frame.ulabel = texture->render(frame.label_w, frame.label_h, frame.ulabel);
|
|
|
|
if (! frame.ulabel)
|
|
|
|
frame.ulabel_pixel = texture->color().pixel();
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
void BlackboxWindow::createHandle(void) {
|
|
|
|
frame.handle = createChildWindow(frame.window);
|
|
|
|
blackbox->saveWindowSearch(frame.handle, this);
|
|
|
|
|
|
|
|
frame.left_grip =
|
|
|
|
createChildWindow(frame.handle, blackbox->getLowerLeftAngleCursor());
|
|
|
|
blackbox->saveWindowSearch(frame.left_grip, this);
|
|
|
|
|
|
|
|
frame.right_grip =
|
|
|
|
createChildWindow(frame.handle, blackbox->getLowerRightAngleCursor());
|
|
|
|
blackbox->saveWindowSearch(frame.right_grip, this);
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
void BlackboxWindow::destroyHandle(void) {
|
|
|
|
if (frame.fhandle)
|
|
|
|
screen->getImageControl()->removeImage(frame.fhandle);
|
|
|
|
|
|
|
|
if (frame.uhandle)
|
|
|
|
screen->getImageControl()->removeImage(frame.uhandle);
|
|
|
|
|
|
|
|
if (frame.fgrip)
|
|
|
|
screen->getImageControl()->removeImage(frame.fgrip);
|
|
|
|
|
|
|
|
if (frame.ugrip)
|
|
|
|
screen->getImageControl()->removeImage(frame.ugrip);
|
|
|
|
|
|
|
|
blackbox->removeWindowSearch(frame.left_grip);
|
|
|
|
blackbox->removeWindowSearch(frame.right_grip);
|
|
|
|
|
|
|
|
XDestroyWindow(blackbox->getXDisplay(), frame.left_grip);
|
|
|
|
XDestroyWindow(blackbox->getXDisplay(), frame.right_grip);
|
|
|
|
frame.left_grip = frame.right_grip = None;
|
|
|
|
|
|
|
|
blackbox->removeWindowSearch(frame.handle);
|
|
|
|
XDestroyWindow(blackbox->getXDisplay(), frame.handle);
|
|
|
|
frame.handle = None;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
void BlackboxWindow::createTitlebar(void) {
|
|
|
|
frame.title = createChildWindow(frame.window);
|
|
|
|
frame.label = createChildWindow(frame.title);
|
|
|
|
blackbox->saveWindowSearch(frame.title, this);
|
|
|
|
blackbox->saveWindowSearch(frame.label, this);
|
|
|
|
|
|
|
|
if (decorations & Decor_Iconify) createIconifyButton();
|
|
|
|
if (decorations & Decor_Maximize) createMaximizeButton();
|
|
|
|
if (decorations & Decor_Close) createCloseButton();
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
void BlackboxWindow::destroyTitlebar(void) {
|
|
|
|
if (frame.close_button)
|
|
|
|
destroyCloseButton();
|
|
|
|
|
|
|
|
if (frame.iconify_button)
|
|
|
|
destroyIconifyButton();
|
|
|
|
|
|
|
|
if (frame.maximize_button)
|
|
|
|
destroyMaximizeButton();
|
|
|
|
|
|
|
|
if (frame.ftitle)
|
|
|
|
screen->getImageControl()->removeImage(frame.ftitle);
|
|
|
|
|
|
|
|
if (frame.utitle)
|
|
|
|
screen->getImageControl()->removeImage(frame.utitle);
|
|
|
|
|
|
|
|
if (frame.flabel)
|
|
|
|
screen->getImageControl()->removeImage(frame.flabel);
|
|
|
|
|
|
|
|
if( frame.ulabel)
|
|
|
|
screen->getImageControl()->removeImage(frame.ulabel);
|
|
|
|
|
|
|
|
if (frame.fbutton)
|
|
|
|
screen->getImageControl()->removeImage(frame.fbutton);
|
|
|
|
|
|
|
|
if (frame.ubutton)
|
|
|
|
screen->getImageControl()->removeImage(frame.ubutton);
|
|
|
|
|
|
|
|
if (frame.pbutton)
|
|
|
|
screen->getImageControl()->removeImage(frame.pbutton);
|
|
|
|
|
|
|
|
blackbox->removeWindowSearch(frame.title);
|
|
|
|
blackbox->removeWindowSearch(frame.label);
|
|
|
|
|
|
|
|
XDestroyWindow(blackbox->getXDisplay(), frame.label);
|
|
|
|
XDestroyWindow(blackbox->getXDisplay(), frame.title);
|
|
|
|
frame.title = frame.label = None;
|
2002-04-11 03:20:38 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
|
2002-05-25 00:29:44 +00:00
|
|
|
void BlackboxWindow::createCloseButton(void) {
|
|
|
|
if (frame.title != None) {
|
2002-04-11 03:20:38 +00:00
|
|
|
frame.close_button = createChildWindow(frame.title);
|
2002-05-25 00:29:44 +00:00
|
|
|
blackbox->saveWindowSearch(frame.close_button, this);
|
2002-04-11 03:20:38 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2002-05-25 00:29:44 +00:00
|
|
|
void BlackboxWindow::destroyCloseButton(void) {
|
|
|
|
blackbox->removeWindowSearch(frame.close_button);
|
|
|
|
XDestroyWindow(blackbox->getXDisplay(), frame.close_button);
|
|
|
|
frame.close_button = None;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
void BlackboxWindow::createIconifyButton(void) {
|
|
|
|
if (frame.title != None) {
|
2002-04-11 03:20:38 +00:00
|
|
|
frame.iconify_button = createChildWindow(frame.title);
|
2002-05-25 00:29:44 +00:00
|
|
|
blackbox->saveWindowSearch(frame.iconify_button, this);
|
2002-04-11 03:20:38 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2002-05-25 00:29:44 +00:00
|
|
|
void BlackboxWindow::destroyIconifyButton(void) {
|
|
|
|
blackbox->removeWindowSearch(frame.iconify_button);
|
|
|
|
XDestroyWindow(blackbox->getXDisplay(), frame.iconify_button);
|
|
|
|
frame.iconify_button = None;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
void BlackboxWindow::createMaximizeButton(void) {
|
|
|
|
if (frame.title != None) {
|
2002-04-11 03:20:38 +00:00
|
|
|
frame.maximize_button = createChildWindow(frame.title);
|
2002-05-25 00:29:44 +00:00
|
|
|
blackbox->saveWindowSearch(frame.maximize_button, this);
|
2002-04-11 03:20:38 +00:00
|
|
|
}
|
2002-05-25 00:29:44 +00:00
|
|
|
}
|
|
|
|
|
2002-04-11 03:20:38 +00:00
|
|
|
|
2002-05-25 00:29:44 +00:00
|
|
|
void BlackboxWindow::destroyMaximizeButton(void) {
|
|
|
|
blackbox->removeWindowSearch(frame.maximize_button);
|
|
|
|
XDestroyWindow(blackbox->getXDisplay(), frame.maximize_button);
|
|
|
|
frame.maximize_button = None;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
void BlackboxWindow::positionButtons(bool redecorate_label) {
|
2002-05-27 03:12:21 +00:00
|
|
|
string layout = blackbox->getTitlebarLayout();
|
|
|
|
string parsed;
|
|
|
|
|
|
|
|
bool hasclose, hasiconify, hasmaximize, haslabel;
|
|
|
|
hasclose = hasiconify = hasmaximize = haslabel = false;
|
|
|
|
|
|
|
|
string::const_iterator it, end;
|
|
|
|
for (it = layout.begin(), end = layout.end(); it != end; ++it) {
|
|
|
|
switch(*it) {
|
|
|
|
case 'C':
|
|
|
|
if (! hasclose && (decorations & Decor_Close)) {
|
|
|
|
hasclose = true;
|
|
|
|
parsed += *it;
|
|
|
|
}
|
|
|
|
break;
|
|
|
|
case 'I':
|
|
|
|
if (! hasiconify && (decorations & Decor_Iconify)) {
|
|
|
|
hasiconify = true;
|
|
|
|
parsed += *it;
|
|
|
|
}
|
|
|
|
break;
|
|
|
|
case 'M':
|
|
|
|
if (! hasmaximize && (decorations & Decor_Maximize)) {
|
|
|
|
hasmaximize = true;
|
|
|
|
parsed += *it;
|
|
|
|
}
|
|
|
|
break;
|
|
|
|
case 'L':
|
|
|
|
if (! haslabel) {
|
|
|
|
haslabel = true;
|
|
|
|
parsed += *it;
|
|
|
|
}
|
|
|
|
}
|
2002-04-11 03:20:38 +00:00
|
|
|
}
|
2002-05-28 09:38:40 +00:00
|
|
|
if (! hasclose && frame.close_button)
|
2002-05-25 00:29:44 +00:00
|
|
|
destroyCloseButton();
|
2002-05-28 09:38:40 +00:00
|
|
|
if (! hasiconify && frame.iconify_button)
|
|
|
|
destroyIconifyButton();
|
|
|
|
if (! hasmaximize && frame.maximize_button)
|
|
|
|
destroyMaximizeButton();
|
2002-05-27 03:12:21 +00:00
|
|
|
if (! haslabel)
|
|
|
|
parsed += 'L'; // require that the label be in the layout
|
|
|
|
|
|
|
|
const unsigned int bsep = frame.bevel_w + 1; // separation between elements
|
|
|
|
const unsigned int by = frame.bevel_w + 1;
|
|
|
|
const unsigned int ty = frame.bevel_w;
|
|
|
|
|
|
|
|
frame.label_w = frame.inside_w - bsep * 2 -
|
|
|
|
(frame.button_w + bsep) * (parsed.size() - 1);
|
|
|
|
|
|
|
|
unsigned int x = bsep;
|
|
|
|
for (it = parsed.begin(), end = parsed.end(); it != end; ++it) {
|
|
|
|
switch(*it) {
|
|
|
|
case 'C':
|
2002-06-21 20:40:14 +00:00
|
|
|
if (! frame.close_button) createCloseButton();
|
2002-05-27 03:12:21 +00:00
|
|
|
XMoveResizeWindow(blackbox->getXDisplay(), frame.close_button, x, by,
|
|
|
|
frame.button_w, frame.button_w);
|
|
|
|
x += frame.button_w + bsep;
|
|
|
|
break;
|
|
|
|
case 'I':
|
2002-06-21 20:40:14 +00:00
|
|
|
if (! frame.iconify_button) createIconifyButton();
|
2002-05-27 03:12:21 +00:00
|
|
|
XMoveResizeWindow(blackbox->getXDisplay(), frame.iconify_button, x, by,
|
|
|
|
frame.button_w, frame.button_w);
|
|
|
|
x += frame.button_w + bsep;
|
|
|
|
break;
|
|
|
|
case 'M':
|
2002-06-21 20:40:14 +00:00
|
|
|
if (! frame.maximize_button) createMaximizeButton();
|
2002-05-27 03:12:21 +00:00
|
|
|
XMoveResizeWindow(blackbox->getXDisplay(), frame.maximize_button, x, by,
|
|
|
|
frame.button_w, frame.button_w);
|
|
|
|
x += frame.button_w + bsep;
|
|
|
|
break;
|
|
|
|
case 'L':
|
|
|
|
XMoveResizeWindow(blackbox->getXDisplay(), frame.label, x, ty,
|
|
|
|
frame.label_w, frame.label_h);
|
|
|
|
x += frame.label_w + bsep;
|
|
|
|
break;
|
|
|
|
}
|
2002-04-11 03:20:38 +00:00
|
|
|
}
|
2002-05-25 00:29:44 +00:00
|
|
|
|
|
|
|
if (redecorate_label) decorateLabel();
|
2002-04-11 03:20:38 +00:00
|
|
|
redrawLabel();
|
|
|
|
redrawAllButtons();
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2002-05-25 00:29:44 +00:00
|
|
|
void BlackboxWindow::reconfigure(void) {
|
2002-04-11 03:20:38 +00:00
|
|
|
upsize();
|
|
|
|
|
2002-05-25 00:29:44 +00:00
|
|
|
client.rect.setPos(frame.rect.left() + frame.margin.left,
|
|
|
|
frame.rect.top() + frame.margin.top);
|
2002-04-11 03:20:38 +00:00
|
|
|
|
|
|
|
positionWindows();
|
|
|
|
decorate();
|
|
|
|
|
2002-05-25 00:29:44 +00:00
|
|
|
XClearWindow(blackbox->getXDisplay(), frame.window);
|
2002-04-11 03:20:38 +00:00
|
|
|
setFocusFlag(flags.focused);
|
|
|
|
|
2002-05-25 00:29:44 +00:00
|
|
|
configure(frame.rect.x(), frame.rect.y(),
|
|
|
|
frame.rect.width(), frame.rect.height());
|
2002-04-11 03:20:38 +00:00
|
|
|
|
|
|
|
if (windowmenu) {
|
2002-05-25 00:29:44 +00:00
|
|
|
windowmenu->move(windowmenu->getX(), frame.rect.y() + frame.title_h);
|
2002-04-11 03:20:38 +00:00
|
|
|
windowmenu->reconfigure();
|
|
|
|
}
|
2002-05-25 00:29:44 +00:00
|
|
|
}
|
|
|
|
|
2002-05-16 22:35:59 +00:00
|
|
|
|
2002-05-25 00:29:44 +00:00
|
|
|
void BlackboxWindow::positionWindows(void) {
|
|
|
|
XMoveResizeWindow(blackbox->getXDisplay(), frame.window,
|
|
|
|
frame.rect.x(), frame.rect.y(), frame.inside_w,
|
|
|
|
(flags.shaded) ? frame.title_h : frame.inside_h);
|
|
|
|
XSetWindowBorderWidth(blackbox->getXDisplay(), frame.window, frame.border_w);
|
|
|
|
XSetWindowBorderWidth(blackbox->getXDisplay(), frame.plate,
|
|
|
|
frame.mwm_border_w);
|
|
|
|
XMoveResizeWindow(blackbox->getXDisplay(), frame.plate,
|
|
|
|
frame.margin.left - frame.mwm_border_w - frame.border_w,
|
|
|
|
frame.margin.top - frame.mwm_border_w - frame.border_w,
|
|
|
|
client.rect.width(), client.rect.height());
|
|
|
|
XMoveResizeWindow(blackbox->getXDisplay(), client.window,
|
|
|
|
0, 0, client.rect.width(), client.rect.height());
|
2002-04-11 03:20:38 +00:00
|
|
|
|
2002-05-25 00:29:44 +00:00
|
|
|
if (decorations & Decor_Titlebar) {
|
|
|
|
if (frame.title == None) createTitlebar();
|
|
|
|
|
|
|
|
XSetWindowBorderWidth(blackbox->getXDisplay(), frame.title,
|
|
|
|
frame.border_w);
|
|
|
|
XMoveResizeWindow(blackbox->getXDisplay(), frame.title, -frame.border_w,
|
|
|
|
-frame.border_w, frame.inside_w, frame.title_h);
|
2002-04-11 03:20:38 +00:00
|
|
|
|
|
|
|
positionButtons();
|
2002-05-25 00:29:44 +00:00
|
|
|
XMapSubwindows(blackbox->getXDisplay(), frame.title);
|
|
|
|
XMapWindow(blackbox->getXDisplay(), frame.title);
|
2002-04-11 03:20:38 +00:00
|
|
|
} else if (frame.title) {
|
2002-05-25 00:29:44 +00:00
|
|
|
destroyTitlebar();
|
|
|
|
}
|
|
|
|
if (decorations & Decor_Handle) {
|
|
|
|
if (frame.handle == None) createHandle();
|
|
|
|
XSetWindowBorderWidth(blackbox->getXDisplay(), frame.handle,
|
|
|
|
frame.border_w);
|
|
|
|
XSetWindowBorderWidth(blackbox->getXDisplay(), frame.left_grip,
|
|
|
|
frame.border_w);
|
|
|
|
XSetWindowBorderWidth(blackbox->getXDisplay(), frame.right_grip,
|
|
|
|
frame.border_w);
|
|
|
|
|
2002-05-28 09:53:11 +00:00
|
|
|
// use client.rect here so the value is correct even if shaded
|
2002-05-25 00:29:44 +00:00
|
|
|
XMoveResizeWindow(blackbox->getXDisplay(), frame.handle,
|
|
|
|
-frame.border_w,
|
2002-05-28 09:53:11 +00:00
|
|
|
client.rect.height() + frame.margin.top +
|
2002-05-25 00:29:44 +00:00
|
|
|
frame.mwm_border_w - frame.border_w,
|
|
|
|
frame.inside_w, frame.handle_h);
|
|
|
|
XMoveResizeWindow(blackbox->getXDisplay(), frame.left_grip,
|
|
|
|
-frame.border_w, -frame.border_w,
|
|
|
|
frame.grip_w, frame.handle_h);
|
|
|
|
XMoveResizeWindow(blackbox->getXDisplay(), frame.right_grip,
|
|
|
|
frame.inside_w - frame.grip_w - frame.border_w,
|
|
|
|
-frame.border_w, frame.grip_w, frame.handle_h);
|
2002-05-28 09:53:11 +00:00
|
|
|
|
2002-05-25 00:29:44 +00:00
|
|
|
XMapSubwindows(blackbox->getXDisplay(), frame.handle);
|
|
|
|
XMapWindow(blackbox->getXDisplay(), frame.handle);
|
2002-04-11 03:20:38 +00:00
|
|
|
} else if (frame.handle) {
|
2002-05-25 00:29:44 +00:00
|
|
|
destroyHandle();
|
2002-04-11 03:20:38 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2002-06-21 20:40:14 +00:00
|
|
|
void BlackboxWindow::updateStrut(void) {
|
|
|
|
unsigned long num = 4;
|
|
|
|
unsigned long *data;
|
|
|
|
if (! xatom->getValue(client.window, XAtom::net_wm_strut, XAtom::cardinal,
|
|
|
|
num, &data))
|
|
|
|
return;
|
|
|
|
|
|
|
|
if (num == 4) {
|
|
|
|
client.strut.left = data[0];
|
|
|
|
client.strut.right = data[1];
|
|
|
|
client.strut.top = data[2];
|
|
|
|
client.strut.bottom = data[3];
|
|
|
|
|
|
|
|
screen->updateAvailableArea();
|
|
|
|
}
|
|
|
|
|
|
|
|
delete [] data;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
void BlackboxWindow::getWindowType(void) {
|
|
|
|
unsigned long val;
|
|
|
|
if (xatom->getValue(client.window, XAtom::net_wm_window_type, XAtom::atom,
|
|
|
|
val)) {
|
|
|
|
if (val == xatom->getAtom(XAtom::net_wm_window_type_desktop))
|
|
|
|
window_type = Type_Desktop;
|
|
|
|
else if (val == xatom->getAtom(XAtom::net_wm_window_type_dock))
|
|
|
|
window_type = Type_Dock;
|
|
|
|
else if (val == xatom->getAtom(XAtom::net_wm_window_type_toolbar))
|
|
|
|
window_type = Type_Toolbar;
|
|
|
|
else if (val == xatom->getAtom(XAtom::net_wm_window_type_menu))
|
|
|
|
window_type = Type_Menu;
|
|
|
|
else if (val == xatom->getAtom(XAtom::net_wm_window_type_utility))
|
|
|
|
window_type = Type_Utility;
|
|
|
|
else if (val == xatom->getAtom(XAtom::net_wm_window_type_splash))
|
|
|
|
window_type = Type_Splash;
|
|
|
|
else if (val == xatom->getAtom(XAtom::net_wm_window_type_dialog))
|
|
|
|
window_type = Type_Dialog;
|
|
|
|
else //if (val[0] == xatom->getAtom(XAtom::net_wm_window_type_normal))
|
|
|
|
window_type = Type_Normal;
|
|
|
|
return;
|
|
|
|
}
|
2002-04-11 03:20:38 +00:00
|
|
|
|
2002-06-21 20:40:14 +00:00
|
|
|
/*
|
|
|
|
* the window type hint was not set, which means we either classify ourself
|
|
|
|
* as a normal window or a dialog, depending on if we are a transient.
|
|
|
|
*/
|
|
|
|
if (isTransient())
|
|
|
|
window_type = Type_Dialog;
|
|
|
|
|
|
|
|
window_type = Type_Normal;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
void BlackboxWindow::getWMName(void) {
|
|
|
|
if (xatom->getValue(client.window, XAtom::net_wm_name,
|
|
|
|
XAtom::utf8, client.title) &&
|
|
|
|
!client.title.empty()) {
|
|
|
|
xatom->eraseValue(client.window, XAtom::net_wm_visible_name);
|
|
|
|
return;
|
2002-04-11 03:20:38 +00:00
|
|
|
}
|
2002-06-21 20:40:14 +00:00
|
|
|
//fall through to using WM_NAME
|
|
|
|
if (xatom->getValue(client.window, XAtom::wm_name, XAtom::ansi, client.title)
|
|
|
|
&& !client.title.empty()) {
|
|
|
|
xatom->eraseValue(client.window, XAtom::net_wm_visible_name);
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
// fall back to an internal default
|
|
|
|
client.title = i18n(WindowSet, WindowUnnamed, "Unnamed");
|
|
|
|
xatom->setValue(client.window, XAtom::net_wm_visible_name, XAtom::utf8,
|
|
|
|
client.title);
|
2002-04-11 03:20:38 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
|
2002-05-25 00:29:44 +00:00
|
|
|
void BlackboxWindow::getWMIconName(void) {
|
2002-06-21 20:40:14 +00:00
|
|
|
if (xatom->getValue(client.window, XAtom::net_wm_icon_name,
|
|
|
|
XAtom::utf8, client.icon_title) &&
|
|
|
|
!client.icon_title.empty()) {
|
|
|
|
xatom->eraseValue(client.window, XAtom::net_wm_visible_icon_name);
|
|
|
|
return;
|
2002-04-11 03:20:38 +00:00
|
|
|
}
|
2002-06-21 20:40:14 +00:00
|
|
|
//fall through to using WM_ICON_NAME
|
|
|
|
if (xatom->getValue(client.window, XAtom::wm_icon_name, XAtom::ansi,
|
|
|
|
client.icon_title) &&
|
|
|
|
!client.icon_title.empty()) {
|
|
|
|
xatom->eraseValue(client.window, XAtom::net_wm_visible_icon_name);
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
// fall back to using the main name
|
|
|
|
client.icon_title = client.title;
|
|
|
|
xatom->setValue(client.window, XAtom::net_wm_visible_icon_name, XAtom::utf8,
|
|
|
|
client.icon_title);
|
2002-04-11 03:20:38 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
/*
|
|
|
|
* Retrieve which WM Protocols are supported by the client window.
|
|
|
|
* If the WM_DELETE_WINDOW protocol is supported, add the close button to the
|
|
|
|
* window's decorations and allow the close behavior.
|
|
|
|
* If the WM_TAKE_FOCUS protocol is supported, save a value that indicates
|
|
|
|
* this.
|
|
|
|
*/
|
2002-05-25 00:29:44 +00:00
|
|
|
void BlackboxWindow::getWMProtocols(void) {
|
2002-04-11 03:20:38 +00:00
|
|
|
Atom *proto;
|
|
|
|
int num_return = 0;
|
|
|
|
|
2002-05-25 00:29:44 +00:00
|
|
|
if (XGetWMProtocols(blackbox->getXDisplay(), client.window,
|
|
|
|
&proto, &num_return)) {
|
2002-04-11 03:20:38 +00:00
|
|
|
for (int i = 0; i < num_return; ++i) {
|
2002-06-21 20:40:14 +00:00
|
|
|
if (proto[i] == xatom->getAtom(XAtom::wm_delete_window)) {
|
2002-05-25 00:29:44 +00:00
|
|
|
decorations |= Decor_Close;
|
|
|
|
functions |= Func_Close;
|
2002-06-21 20:40:14 +00:00
|
|
|
} else if (proto[i] == xatom->getAtom(XAtom::wm_take_focus))
|
2002-04-11 03:20:38 +00:00
|
|
|
flags.send_focus_message = True;
|
2002-06-21 20:40:14 +00:00
|
|
|
else if (proto[i] == xatom->getAtom(XAtom::blackbox_structure_messages))
|
2002-05-25 00:29:44 +00:00
|
|
|
screen->addNetizen(new Netizen(screen, client.window));
|
2002-04-11 03:20:38 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
XFree(proto);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
/*
|
|
|
|
* Gets the value of the WM_HINTS property.
|
|
|
|
* If the property is not set, then use a set of default values.
|
|
|
|
*/
|
2002-05-25 00:29:44 +00:00
|
|
|
void BlackboxWindow::getWMHints(void) {
|
|
|
|
focus_mode = F_Passive;
|
|
|
|
client.initial_state = NormalState;
|
|
|
|
|
|
|
|
// remove from current window group
|
|
|
|
if (client.window_group) {
|
|
|
|
BWindowGroup *group = blackbox->searchGroup(client.window_group);
|
|
|
|
if (group) group->removeWindow(this);
|
|
|
|
}
|
|
|
|
client.window_group = None;
|
|
|
|
|
|
|
|
XWMHints *wmhint = XGetWMHints(blackbox->getXDisplay(), client.window);
|
2002-04-11 03:20:38 +00:00
|
|
|
if (! wmhint) {
|
|
|
|
return;
|
|
|
|
}
|
2002-05-25 00:29:44 +00:00
|
|
|
|
2002-04-11 03:20:38 +00:00
|
|
|
if (wmhint->flags & InputHint) {
|
|
|
|
if (wmhint->input == True) {
|
|
|
|
if (flags.send_focus_message)
|
2002-05-16 22:35:59 +00:00
|
|
|
focus_mode = F_LocallyActive;
|
2002-04-11 03:20:38 +00:00
|
|
|
} else {
|
|
|
|
if (flags.send_focus_message)
|
2002-05-16 22:35:59 +00:00
|
|
|
focus_mode = F_GloballyActive;
|
2002-04-11 03:20:38 +00:00
|
|
|
else
|
2002-05-16 22:35:59 +00:00
|
|
|
focus_mode = F_NoInput;
|
2002-04-11 03:20:38 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
if (wmhint->flags & StateHint)
|
|
|
|
client.initial_state = wmhint->initial_state;
|
|
|
|
|
|
|
|
if (wmhint->flags & WindowGroupHint) {
|
2002-05-25 00:29:44 +00:00
|
|
|
client.window_group = wmhint->window_group;
|
|
|
|
|
|
|
|
// add window to the appropriate group
|
|
|
|
BWindowGroup *group = blackbox->searchGroup(client.window_group);
|
|
|
|
if (! group) // no group found, create it!
|
|
|
|
group = new BWindowGroup(blackbox, client.window_group);
|
|
|
|
group->addWindow(this);
|
2002-04-11 03:20:38 +00:00
|
|
|
}
|
2002-05-25 00:29:44 +00:00
|
|
|
|
|
|
|
client.wm_hint_flags = wmhint->flags;
|
2002-04-11 03:20:38 +00:00
|
|
|
XFree(wmhint);
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
/*
|
|
|
|
* Gets the value of the WM_NORMAL_HINTS property.
|
|
|
|
* If the property is not set, then use a set of default values.
|
|
|
|
*/
|
2002-05-25 00:29:44 +00:00
|
|
|
void BlackboxWindow::getWMNormalHints(void) {
|
2002-04-11 03:20:38 +00:00
|
|
|
long icccm_mask;
|
|
|
|
XSizeHints sizehint;
|
|
|
|
|
|
|
|
client.min_width = client.min_height =
|
|
|
|
client.width_inc = client.height_inc = 1;
|
2002-05-25 00:29:44 +00:00
|
|
|
client.base_width = client.base_height = 0;
|
2002-05-26 20:51:33 +00:00
|
|
|
|
|
|
|
/*
|
|
|
|
use the full screen, not the strut modified size. otherwise when the
|
|
|
|
availableArea changes max_width/height will be incorrect and lead to odd
|
|
|
|
rendering bugs.
|
|
|
|
*/
|
|
|
|
const Rect& screen_area = screen->getRect();
|
2002-05-25 00:29:44 +00:00
|
|
|
client.max_width = screen_area.width();
|
2002-05-26 20:51:33 +00:00
|
|
|
|
2002-05-25 00:29:44 +00:00
|
|
|
client.max_height = screen_area.height();
|
2002-04-11 03:20:38 +00:00
|
|
|
client.min_aspect_x = client.min_aspect_y =
|
|
|
|
client.max_aspect_x = client.max_aspect_y = 1;
|
|
|
|
client.win_gravity = NorthWestGravity;
|
|
|
|
|
2002-05-25 00:29:44 +00:00
|
|
|
if (! XGetWMNormalHints(blackbox->getXDisplay(), client.window,
|
|
|
|
&sizehint, &icccm_mask))
|
2002-04-11 03:20:38 +00:00
|
|
|
return;
|
|
|
|
|
|
|
|
client.normal_hint_flags = sizehint.flags;
|
|
|
|
|
|
|
|
if (sizehint.flags & PMinSize) {
|
|
|
|
client.min_width = sizehint.min_width;
|
|
|
|
client.min_height = sizehint.min_height;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (sizehint.flags & PMaxSize) {
|
|
|
|
client.max_width = sizehint.max_width;
|
|
|
|
client.max_height = sizehint.max_height;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (sizehint.flags & PResizeInc) {
|
|
|
|
client.width_inc = sizehint.width_inc;
|
|
|
|
client.height_inc = sizehint.height_inc;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (sizehint.flags & PAspect) {
|
|
|
|
client.min_aspect_x = sizehint.min_aspect.x;
|
|
|
|
client.min_aspect_y = sizehint.min_aspect.y;
|
|
|
|
client.max_aspect_x = sizehint.max_aspect.x;
|
|
|
|
client.max_aspect_y = sizehint.max_aspect.y;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (sizehint.flags & PBaseSize) {
|
|
|
|
client.base_width = sizehint.base_width;
|
|
|
|
client.base_height = sizehint.base_height;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (sizehint.flags & PWinGravity)
|
|
|
|
client.win_gravity = sizehint.win_gravity;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2002-06-21 20:40:14 +00:00
|
|
|
/*
|
|
|
|
* Gets the NETWM hints for the class' contained window.
|
|
|
|
*/
|
|
|
|
void BlackboxWindow::getNetWMHints(void) {
|
|
|
|
unsigned long workspace;
|
|
|
|
|
|
|
|
if (xatom->getValue(client.window, XAtom::net_wm_desktop, XAtom::cardinal,
|
|
|
|
workspace)) {
|
|
|
|
if (workspace == 0xffffffff)
|
|
|
|
flags.stuck = True;
|
|
|
|
else
|
|
|
|
blackbox_attrib.workspace = workspace;
|
|
|
|
}
|
|
|
|
|
|
|
|
unsigned long *state;
|
|
|
|
unsigned long num = (unsigned) -1;
|
|
|
|
if (xatom->getValue(client.window, XAtom::net_wm_state, XAtom::atom,
|
|
|
|
num, &state)) {
|
|
|
|
bool vert = False,
|
|
|
|
horz = False;
|
|
|
|
for (unsigned long i = 0; i < num; ++i) {
|
|
|
|
if (state[i] == xatom->getAtom(XAtom::net_wm_state_modal))
|
|
|
|
flags.modal = True;
|
|
|
|
else if (state[i] == xatom->getAtom(XAtom::net_wm_state_shaded))
|
|
|
|
flags.shaded = True;
|
|
|
|
else if (state[i] == xatom->getAtom(XAtom::net_wm_state_skip_taskbar))
|
|
|
|
flags.skip_taskbar = True;
|
|
|
|
else if (state[i] == xatom->getAtom(XAtom::net_wm_state_skip_pager))
|
|
|
|
flags.skip_pager = True;
|
|
|
|
else if (state[i] == xatom->getAtom(XAtom::net_wm_state_fullscreen))
|
|
|
|
flags.fullscreen = True;
|
|
|
|
else if (state[i] == xatom->getAtom(XAtom::net_wm_state_hidden))
|
|
|
|
setState(IconicState);
|
|
|
|
else if (state[i] == xatom->getAtom(XAtom::net_wm_state_maximized_vert))
|
|
|
|
vert = True;
|
|
|
|
else if (state[i] == xatom->getAtom(XAtom::net_wm_state_maximized_horz))
|
|
|
|
horz = True;
|
|
|
|
}
|
|
|
|
if (vert && horz)
|
|
|
|
flags.maximized = 1;
|
|
|
|
else if (vert)
|
|
|
|
flags.maximized = 2;
|
|
|
|
else if (horz)
|
|
|
|
flags.maximized = 3;
|
|
|
|
|
|
|
|
delete [] state;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2002-04-11 03:20:38 +00:00
|
|
|
/*
|
|
|
|
* Gets the MWM hints for the class' contained window.
|
|
|
|
* This is used while initializing the window to its first state, and not
|
|
|
|
* thereafter.
|
2002-05-25 00:29:44 +00:00
|
|
|
* Returns: true if the MWM hints are successfully retreived and applied;
|
|
|
|
* false if they are not.
|
2002-04-11 03:20:38 +00:00
|
|
|
*/
|
2002-05-25 00:29:44 +00:00
|
|
|
void BlackboxWindow::getMWMHints(void) {
|
2002-06-21 20:40:14 +00:00
|
|
|
unsigned long num;
|
|
|
|
MwmHints *mwm_hint;
|
|
|
|
|
|
|
|
num = PropMwmHintsElements;
|
|
|
|
if (! xatom->getValue(client.window, XAtom::motif_wm_hints,
|
|
|
|
XAtom::motif_wm_hints, num,
|
|
|
|
(unsigned long **)&mwm_hint) ||
|
|
|
|
num < PropMwmHintsElements)
|
2002-04-11 03:20:38 +00:00
|
|
|
return;
|
|
|
|
|
2002-05-25 00:29:44 +00:00
|
|
|
if (mwm_hint->flags & MwmHintsDecorations) {
|
|
|
|
if (mwm_hint->decorations & MwmDecorAll) {
|
|
|
|
decorations = Decor_Titlebar | Decor_Handle | Decor_Border |
|
|
|
|
Decor_Iconify | Decor_Maximize | Decor_Close;
|
2002-04-11 03:20:38 +00:00
|
|
|
} else {
|
2002-05-25 00:29:44 +00:00
|
|
|
decorations = 0;
|
|
|
|
|
|
|
|
if (mwm_hint->decorations & MwmDecorBorder)
|
|
|
|
decorations |= Decor_Border;
|
|
|
|
if (mwm_hint->decorations & MwmDecorHandle)
|
|
|
|
decorations |= Decor_Handle;
|
|
|
|
if (mwm_hint->decorations & MwmDecorTitle)
|
|
|
|
decorations |= Decor_Titlebar;
|
|
|
|
if (mwm_hint->decorations & MwmDecorIconify)
|
|
|
|
decorations |= Decor_Iconify;
|
|
|
|
if (mwm_hint->decorations & MwmDecorMaximize)
|
|
|
|
decorations |= Decor_Maximize;
|
2002-04-11 03:20:38 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2002-05-25 00:29:44 +00:00
|
|
|
if (mwm_hint->flags & MwmHintsFunctions) {
|
|
|
|
if (mwm_hint->functions & MwmFuncAll) {
|
|
|
|
functions = Func_Resize | Func_Move | Func_Iconify | Func_Maximize |
|
|
|
|
Func_Close;
|
2002-04-11 03:20:38 +00:00
|
|
|
} else {
|
2002-05-25 00:29:44 +00:00
|
|
|
functions = 0;
|
|
|
|
|
|
|
|
if (mwm_hint->functions & MwmFuncResize)
|
|
|
|
functions |= Func_Resize;
|
|
|
|
if (mwm_hint->functions & MwmFuncMove)
|
|
|
|
functions |= Func_Move;
|
|
|
|
if (mwm_hint->functions & MwmFuncIconify)
|
|
|
|
functions |= Func_Iconify;
|
|
|
|
if (mwm_hint->functions & MwmFuncMaximize)
|
|
|
|
functions |= Func_Maximize;
|
|
|
|
if (mwm_hint->functions & MwmFuncClose)
|
|
|
|
functions |= Func_Close;
|
2002-04-11 03:20:38 +00:00
|
|
|
}
|
|
|
|
}
|
2002-06-21 20:40:14 +00:00
|
|
|
delete mwm_hint;
|
2002-04-11 03:20:38 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
/*
|
2002-05-25 00:29:44 +00:00
|
|
|
* Gets the blackbox hints from the class' contained window.
|
2002-04-11 03:20:38 +00:00
|
|
|
* This is used while initializing the window to its first state, and not
|
|
|
|
* thereafter.
|
|
|
|
* Returns: true if the hints are successfully retreived and applied; false if
|
|
|
|
* they are not.
|
|
|
|
*/
|
2002-05-25 00:29:44 +00:00
|
|
|
bool BlackboxWindow::getBlackboxHints(void) {
|
2002-06-21 20:40:14 +00:00
|
|
|
unsigned long num;
|
|
|
|
BlackboxHints *blackbox_hint;
|
|
|
|
|
|
|
|
num = PropBlackboxHintsElements;
|
|
|
|
if (! xatom->getValue(client.window, XAtom::blackbox_hints,
|
|
|
|
XAtom::blackbox_hints, num,
|
|
|
|
(unsigned long **)&blackbox_hint) ||
|
|
|
|
num < PropBlackboxHintsElements)
|
2002-05-25 00:29:44 +00:00
|
|
|
return False;
|
2002-04-11 03:20:38 +00:00
|
|
|
|
2002-05-25 00:29:44 +00:00
|
|
|
if (blackbox_hint->flags & AttribShaded)
|
|
|
|
flags.shaded = (blackbox_hint->attrib & AttribShaded);
|
2002-04-11 03:20:38 +00:00
|
|
|
|
2002-05-25 00:29:44 +00:00
|
|
|
if ((blackbox_hint->flags & AttribMaxHoriz) &&
|
|
|
|
(blackbox_hint->flags & AttribMaxVert))
|
|
|
|
flags.maximized = (blackbox_hint->attrib &
|
2002-05-16 22:35:59 +00:00
|
|
|
(AttribMaxHoriz | AttribMaxVert)) ? 1 : 0;
|
2002-05-25 00:29:44 +00:00
|
|
|
else if (blackbox_hint->flags & AttribMaxVert)
|
|
|
|
flags.maximized = (blackbox_hint->attrib & AttribMaxVert) ? 2 : 0;
|
|
|
|
else if (blackbox_hint->flags & AttribMaxHoriz)
|
|
|
|
flags.maximized = (blackbox_hint->attrib & AttribMaxHoriz) ? 3 : 0;
|
2002-04-11 03:20:38 +00:00
|
|
|
|
2002-05-25 00:29:44 +00:00
|
|
|
if (blackbox_hint->flags & AttribOmnipresent)
|
|
|
|
flags.stuck = (blackbox_hint->attrib & AttribOmnipresent);
|
2002-04-11 03:20:38 +00:00
|
|
|
|
2002-05-25 00:29:44 +00:00
|
|
|
if (blackbox_hint->flags & AttribWorkspace)
|
|
|
|
blackbox_attrib.workspace = blackbox_hint->workspace;
|
2002-04-11 03:20:38 +00:00
|
|
|
|
2002-05-25 00:29:44 +00:00
|
|
|
// if (blackbox_hint->flags & AttribStack)
|
|
|
|
// don't yet have always on top/bottom for blackbox yet... working
|
2002-04-11 03:20:38 +00:00
|
|
|
// on that
|
|
|
|
|
2002-05-25 00:29:44 +00:00
|
|
|
if (blackbox_hint->flags & AttribDecoration) {
|
|
|
|
switch (blackbox_hint->decoration) {
|
2002-04-11 03:20:38 +00:00
|
|
|
case DecorNone:
|
2002-05-25 00:29:44 +00:00
|
|
|
// clear all decorations except close
|
|
|
|
decorations &= Decor_Close;
|
|
|
|
// clear all functions except close
|
|
|
|
functions &= Func_Close;
|
2002-04-11 03:20:38 +00:00
|
|
|
|
|
|
|
break;
|
|
|
|
|
|
|
|
case DecorTiny:
|
2002-05-25 00:29:44 +00:00
|
|
|
decorations |= Decor_Titlebar | Decor_Iconify;
|
|
|
|
decorations &= ~(Decor_Border | Decor_Handle | Decor_Maximize);
|
|
|
|
functions |= Func_Move | Func_Iconify;
|
|
|
|
functions &= ~(Func_Resize | Func_Maximize);
|
2002-04-11 03:20:38 +00:00
|
|
|
|
|
|
|
break;
|
|
|
|
|
|
|
|
case DecorTool:
|
2002-05-25 00:29:44 +00:00
|
|
|
decorations |= Decor_Titlebar;
|
|
|
|
decorations &= ~(Decor_Iconify | Decor_Border | Decor_Handle);
|
|
|
|
functions |= Func_Move;
|
|
|
|
functions &= ~(Func_Resize | Func_Maximize | Func_Iconify);
|
2002-04-11 03:20:38 +00:00
|
|
|
|
|
|
|
break;
|
|
|
|
|
|
|
|
case DecorNormal:
|
|
|
|
default:
|
2002-05-25 00:29:44 +00:00
|
|
|
decorations |= Decor_Titlebar | Decor_Border | Decor_Handle |
|
|
|
|
Decor_Iconify | Decor_Maximize;
|
|
|
|
functions |= Func_Resize | Func_Move | Func_Iconify | Func_Maximize;
|
2002-04-11 03:20:38 +00:00
|
|
|
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
|
|
|
|
reconfigure();
|
|
|
|
}
|
2002-06-21 20:40:14 +00:00
|
|
|
|
|
|
|
delete blackbox_hint;
|
|
|
|
|
2002-05-25 00:29:44 +00:00
|
|
|
return True;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
void BlackboxWindow::getTransientInfo(void) {
|
|
|
|
if (client.transient_for &&
|
|
|
|
client.transient_for != (BlackboxWindow *) ~0ul) {
|
|
|
|
// the transient for hint was removed, so we need to tell our
|
|
|
|
// previous transient_for that we are going away
|
|
|
|
client.transient_for->client.transientList.remove(this);
|
|
|
|
}
|
|
|
|
|
|
|
|
// we have no transient_for until we find a new one
|
|
|
|
client.transient_for = 0;
|
|
|
|
|
|
|
|
Window trans_for;
|
2002-05-26 20:25:38 +00:00
|
|
|
if (! XGetTransientForHint(blackbox->getXDisplay(), client.window,
|
|
|
|
&trans_for)) {
|
2002-05-25 00:29:44 +00:00
|
|
|
// transient_for hint not set
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (trans_for == client.window) {
|
|
|
|
// wierd client... treat this window as a normal window
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (trans_for == None || trans_for == screen->getRootWindow()) {
|
|
|
|
// this is an undocumented interpretation of the ICCCM. a transient
|
|
|
|
// associated with None/Root/itself is assumed to be a modal root
|
|
|
|
// transient. we don't support the concept of a global transient,
|
|
|
|
// so we just associate this transient with nothing, and perhaps
|
|
|
|
// we will add support later for global modality.
|
|
|
|
client.transient_for = (BlackboxWindow *) ~0ul;
|
|
|
|
flags.modal = True;
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
client.transient_for = blackbox->searchWindow(trans_for);
|
|
|
|
if (! client.transient_for &&
|
|
|
|
client.window_group && trans_for == client.window_group) {
|
|
|
|
// no direct transient_for, perhaps this is a group transient?
|
|
|
|
BWindowGroup *group = blackbox->searchGroup(client.window_group);
|
|
|
|
if (group) client.transient_for = group->find(screen);
|
|
|
|
}
|
|
|
|
|
|
|
|
if (! client.transient_for || client.transient_for == this) {
|
|
|
|
// no transient_for found, or we have a wierd client that wants to be
|
|
|
|
// a transient for itself, so we treat this window as a normal window
|
|
|
|
client.transient_for = (BlackboxWindow*) 0;
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
// register ourselves with our new transient_for
|
|
|
|
client.transient_for->client.transientList.push_back(this);
|
|
|
|
flags.stuck = client.transient_for->flags.stuck;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2002-06-21 20:40:14 +00:00
|
|
|
bool BlackboxWindow::isKDESystrayWindow(void) {
|
|
|
|
Window systray;
|
|
|
|
if (xatom->getValue(client.window, XAtom::kde_net_wm_system_tray_window_for,
|
|
|
|
XAtom::window, systray) && systray)
|
|
|
|
return True;
|
|
|
|
return False;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2002-05-25 00:29:44 +00:00
|
|
|
BlackboxWindow *BlackboxWindow::getTransientFor(void) const {
|
|
|
|
if (client.transient_for &&
|
|
|
|
client.transient_for != (BlackboxWindow*) ~0ul)
|
|
|
|
return client.transient_for;
|
|
|
|
return 0;
|
2002-04-11 03:20:38 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
|
2002-05-25 00:29:44 +00:00
|
|
|
void BlackboxWindow::configure(int dx, int dy,
|
|
|
|
unsigned int dw, unsigned int dh) {
|
|
|
|
bool send_event = (frame.rect.x() != dx || frame.rect.y() != dy);
|
2002-04-11 03:20:38 +00:00
|
|
|
|
2002-05-25 00:29:44 +00:00
|
|
|
if ((dw != frame.rect.width()) || (dh != frame.rect.height())) {
|
|
|
|
frame.rect.setRect(dx, dy, dw, dh);
|
|
|
|
frame.inside_w = frame.rect.width() - (frame.border_w * 2);
|
|
|
|
frame.inside_h = frame.rect.height() - (frame.border_w * 2);
|
2002-04-11 03:20:38 +00:00
|
|
|
|
2002-05-25 00:29:44 +00:00
|
|
|
if (frame.rect.right() <= 0 || frame.rect.bottom() <= 0)
|
|
|
|
frame.rect.setPos(0, 0);
|
2002-04-11 03:20:38 +00:00
|
|
|
|
2002-05-25 00:29:44 +00:00
|
|
|
client.rect.setCoords(frame.rect.left() + frame.margin.left,
|
|
|
|
frame.rect.top() + frame.margin.top,
|
|
|
|
frame.rect.right() - frame.margin.right,
|
|
|
|
frame.rect.bottom() - frame.margin.bottom);
|
2002-04-11 03:20:38 +00:00
|
|
|
|
|
|
|
#ifdef SHAPE
|
2002-05-25 00:29:44 +00:00
|
|
|
if (blackbox->hasShapeExtensions() && flags.shaped) {
|
|
|
|
configureShape();
|
2002-04-11 03:20:38 +00:00
|
|
|
}
|
|
|
|
#endif // SHAPE
|
|
|
|
|
|
|
|
positionWindows();
|
|
|
|
decorate();
|
2002-05-25 00:29:44 +00:00
|
|
|
setFocusFlag(flags.focused);
|
|
|
|
redrawAllButtons();
|
2002-04-11 03:20:38 +00:00
|
|
|
} else {
|
2002-05-25 00:29:44 +00:00
|
|
|
frame.rect.setPos(dx, dy);
|
2002-04-11 03:20:38 +00:00
|
|
|
|
2002-05-25 00:29:44 +00:00
|
|
|
XMoveWindow(blackbox->getXDisplay(), frame.window,
|
|
|
|
frame.rect.x(), frame.rect.y());
|
2002-04-11 03:20:38 +00:00
|
|
|
|
|
|
|
if (! flags.moving) send_event = True;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (send_event && ! flags.moving) {
|
2002-05-25 00:29:44 +00:00
|
|
|
client.rect.setPos(frame.rect.left() + frame.margin.left,
|
|
|
|
frame.rect.top() + frame.margin.top);
|
2002-04-11 03:20:38 +00:00
|
|
|
|
|
|
|
XEvent event;
|
|
|
|
event.type = ConfigureNotify;
|
|
|
|
|
2002-05-25 00:29:44 +00:00
|
|
|
event.xconfigure.display = blackbox->getXDisplay();
|
2002-04-11 03:20:38 +00:00
|
|
|
event.xconfigure.event = client.window;
|
|
|
|
event.xconfigure.window = client.window;
|
2002-05-25 00:29:44 +00:00
|
|
|
event.xconfigure.x = client.rect.x();
|
|
|
|
event.xconfigure.y = client.rect.y();
|
|
|
|
event.xconfigure.width = client.rect.width();
|
|
|
|
event.xconfigure.height = client.rect.height();
|
2002-04-11 03:20:38 +00:00
|
|
|
event.xconfigure.border_width = client.old_bw;
|
|
|
|
event.xconfigure.above = frame.window;
|
|
|
|
event.xconfigure.override_redirect = False;
|
|
|
|
|
2002-05-25 00:29:44 +00:00
|
|
|
XSendEvent(blackbox->getXDisplay(), client.window, True,
|
|
|
|
NoEventMask, &event);
|
2002-04-11 03:20:38 +00:00
|
|
|
|
|
|
|
screen->updateNetizenConfigNotify(&event);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2002-05-25 00:29:44 +00:00
|
|
|
#ifdef SHAPE
|
|
|
|
void BlackboxWindow::configureShape(void) {
|
|
|
|
XShapeCombineShape(blackbox->getXDisplay(), frame.window, ShapeBounding,
|
|
|
|
frame.margin.left - frame.border_w,
|
|
|
|
frame.margin.top - frame.border_w,
|
|
|
|
client.window, ShapeBounding, ShapeSet);
|
2002-04-11 03:20:38 +00:00
|
|
|
|
2002-05-25 00:29:44 +00:00
|
|
|
int num = 0;
|
|
|
|
XRectangle xrect[2];
|
2002-04-11 03:20:38 +00:00
|
|
|
|
2002-05-25 00:29:44 +00:00
|
|
|
if (decorations & Decor_Titlebar) {
|
|
|
|
xrect[0].x = xrect[0].y = -frame.border_w;
|
|
|
|
xrect[0].width = frame.rect.width();
|
|
|
|
xrect[0].height = frame.title_h + (frame.border_w * 2);
|
|
|
|
++num;
|
2002-04-11 03:20:38 +00:00
|
|
|
}
|
|
|
|
|
2002-05-25 00:29:44 +00:00
|
|
|
if (decorations & Decor_Handle) {
|
|
|
|
xrect[1].x = -frame.border_w;
|
|
|
|
xrect[1].y = frame.rect.height() - frame.margin.bottom +
|
|
|
|
frame.mwm_border_w - frame.border_w;
|
|
|
|
xrect[1].width = frame.rect.width();
|
|
|
|
xrect[1].height = frame.handle_h + (frame.border_w * 2);
|
|
|
|
++num;
|
|
|
|
}
|
2002-04-11 03:20:38 +00:00
|
|
|
|
2002-05-25 00:29:44 +00:00
|
|
|
XShapeCombineRectangles(blackbox->getXDisplay(), frame.window,
|
|
|
|
ShapeBounding, 0, 0, xrect, num,
|
|
|
|
ShapeUnion, Unsorted);
|
2002-04-11 03:20:38 +00:00
|
|
|
}
|
2002-05-25 00:29:44 +00:00
|
|
|
#endif // SHAPE
|
2002-04-11 03:20:38 +00:00
|
|
|
|
|
|
|
|
2002-05-25 00:29:44 +00:00
|
|
|
bool BlackboxWindow::setInputFocus(void) {
|
|
|
|
if (flags.focused) return True;
|
2002-04-11 03:20:38 +00:00
|
|
|
|
2002-06-21 01:06:29 +00:00
|
|
|
assert(! flags.iconic);
|
|
|
|
|
|
|
|
// if the window is not visible, mark the window as wanting focus rather
|
|
|
|
// than give it focus.
|
|
|
|
if (! flags.visible) {
|
|
|
|
Workspace *wkspc = screen->getWorkspace(blackbox_attrib.workspace);
|
|
|
|
wkspc->setLastFocusedWindow(this);
|
|
|
|
return True;
|
|
|
|
}
|
|
|
|
|
2002-05-25 00:29:44 +00:00
|
|
|
if (! client.rect.intersects(screen->getRect())) {
|
|
|
|
// client is outside the screen, move it to the center
|
|
|
|
configure((screen->getWidth() - frame.rect.width()) / 2,
|
|
|
|
(screen->getHeight() - frame.rect.height()) / 2,
|
|
|
|
frame.rect.width(), frame.rect.height());
|
|
|
|
}
|
|
|
|
|
|
|
|
if (client.transientList.size() > 0) {
|
|
|
|
// transfer focus to any modal transients
|
|
|
|
BlackboxWindowList::iterator it, end = client.transientList.end();
|
|
|
|
for (it = client.transientList.begin(); it != end; ++it) {
|
|
|
|
if ((*it)->flags.modal) return (*it)->setInputFocus();
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
bool ret = True;
|
|
|
|
if (focus_mode == F_LocallyActive || focus_mode == F_Passive) {
|
|
|
|
XSetInputFocus(blackbox->getXDisplay(), client.window,
|
|
|
|
RevertToPointerRoot, CurrentTime);
|
|
|
|
|
|
|
|
blackbox->setFocusedWindow(this);
|
|
|
|
} else {
|
|
|
|
/* we could set the focus to none, since the window doesn't accept focus,
|
|
|
|
* but we shouldn't set focus to nothing since this would surely make
|
|
|
|
* someone angry
|
|
|
|
*/
|
|
|
|
ret = False;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (flags.send_focus_message) {
|
|
|
|
XEvent ce;
|
|
|
|
ce.xclient.type = ClientMessage;
|
2002-06-21 20:40:14 +00:00
|
|
|
ce.xclient.message_type = xatom->getAtom(XAtom::wm_protocols);
|
2002-05-25 00:29:44 +00:00
|
|
|
ce.xclient.display = blackbox->getXDisplay();
|
|
|
|
ce.xclient.window = client.window;
|
|
|
|
ce.xclient.format = 32;
|
2002-06-21 20:40:14 +00:00
|
|
|
ce.xclient.data.l[0] = xatom->getAtom(XAtom::wm_take_focus);
|
2002-05-25 00:29:44 +00:00
|
|
|
ce.xclient.data.l[1] = blackbox->getLastTime();
|
|
|
|
ce.xclient.data.l[2] = 0l;
|
|
|
|
ce.xclient.data.l[3] = 0l;
|
|
|
|
ce.xclient.data.l[4] = 0l;
|
|
|
|
XSendEvent(blackbox->getXDisplay(), client.window, False,
|
|
|
|
NoEventMask, &ce);
|
|
|
|
}
|
|
|
|
|
|
|
|
return ret;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
void BlackboxWindow::iconify(void) {
|
|
|
|
if (flags.iconic) return;
|
2002-04-28 19:17:16 +00:00
|
|
|
|
2002-06-21 20:40:14 +00:00
|
|
|
// We don't need to worry about resizing because resizing always grabs the X
|
|
|
|
// server. This should only ever happen if using opaque moving.
|
|
|
|
if (flags.moving)
|
|
|
|
endMove();
|
|
|
|
|
2002-04-11 03:20:38 +00:00
|
|
|
if (windowmenu) windowmenu->hide();
|
|
|
|
|
2002-05-25 00:29:44 +00:00
|
|
|
/*
|
|
|
|
* we don't want this XUnmapWindow call to generate an UnmapNotify event, so
|
|
|
|
* we need to clear the event mask on client.window for a split second.
|
|
|
|
* HOWEVER, since X11 is asynchronous, the window could be destroyed in that
|
|
|
|
* split second, leaving us with a ghost window... so, we need to do this
|
|
|
|
* while the X server is grabbed
|
|
|
|
*/
|
|
|
|
XGrabServer(blackbox->getXDisplay());
|
|
|
|
XSelectInput(blackbox->getXDisplay(), client.window, NoEventMask);
|
|
|
|
XUnmapWindow(blackbox->getXDisplay(), client.window);
|
|
|
|
XSelectInput(blackbox->getXDisplay(), client.window,
|
|
|
|
PropertyChangeMask | FocusChangeMask | StructureNotifyMask);
|
|
|
|
XUngrabServer(blackbox->getXDisplay());
|
|
|
|
|
|
|
|
XUnmapWindow(blackbox->getXDisplay(), frame.window);
|
2002-04-11 03:20:38 +00:00
|
|
|
flags.visible = False;
|
|
|
|
flags.iconic = True;
|
|
|
|
|
2002-06-21 20:40:14 +00:00
|
|
|
setState(IconicState);
|
|
|
|
|
2002-05-25 00:29:44 +00:00
|
|
|
screen->getWorkspace(blackbox_attrib.workspace)->removeWindow(this);
|
2002-04-11 03:20:38 +00:00
|
|
|
|
2002-05-25 00:29:44 +00:00
|
|
|
if (isTransient()) {
|
|
|
|
if (client.transient_for != (BlackboxWindow *) ~0ul &&
|
|
|
|
! client.transient_for->flags.iconic) {
|
|
|
|
// iconify our transient_for
|
|
|
|
client.transient_for->iconify();
|
|
|
|
}
|
2002-04-11 03:20:38 +00:00
|
|
|
}
|
2002-05-25 00:29:44 +00:00
|
|
|
|
2002-04-11 03:20:38 +00:00
|
|
|
screen->addIcon(this);
|
|
|
|
|
2002-05-25 00:29:44 +00:00
|
|
|
if (client.transientList.size() > 0) {
|
|
|
|
// iconify all transients
|
|
|
|
BlackboxWindowList::iterator it, end = client.transientList.end();
|
|
|
|
for (it = client.transientList.begin(); it != end; ++it) {
|
|
|
|
if (! (*it)->flags.iconic) (*it)->iconify();
|
|
|
|
}
|
2002-04-11 03:20:38 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2002-05-25 00:29:44 +00:00
|
|
|
void BlackboxWindow::show(void) {
|
2002-06-21 20:40:14 +00:00
|
|
|
flags.visible = True;
|
|
|
|
flags.iconic = False;
|
|
|
|
|
2002-06-21 01:06:29 +00:00
|
|
|
current_state = (flags.shaded) ? IconicState : NormalState;
|
|
|
|
setState(current_state);
|
2002-04-11 03:20:38 +00:00
|
|
|
|
2002-05-25 00:29:44 +00:00
|
|
|
XMapWindow(blackbox->getXDisplay(), client.window);
|
|
|
|
XMapSubwindows(blackbox->getXDisplay(), frame.window);
|
|
|
|
XMapWindow(blackbox->getXDisplay(), frame.window);
|
|
|
|
}
|
2002-04-11 03:20:38 +00:00
|
|
|
|
2002-05-16 22:35:59 +00:00
|
|
|
|
2002-06-29 23:50:04 +00:00
|
|
|
void BlackboxWindow::deiconify(bool reassoc, bool doraise) {
|
2002-05-25 00:29:44 +00:00
|
|
|
if (flags.iconic || reassoc)
|
|
|
|
screen->reassociateWindow(this, BSENTINEL, False);
|
|
|
|
else if (blackbox_attrib.workspace != screen->getCurrentWorkspace()->getID())
|
|
|
|
return;
|
2002-04-11 03:20:38 +00:00
|
|
|
|
2002-05-25 00:29:44 +00:00
|
|
|
show();
|
2002-04-11 03:20:38 +00:00
|
|
|
|
2002-05-25 00:29:44 +00:00
|
|
|
// reassociate and deiconify all transients
|
|
|
|
if (reassoc && client.transientList.size() > 0) {
|
|
|
|
BlackboxWindowList::iterator it, end = client.transientList.end();
|
|
|
|
for (it = client.transientList.begin(); it != end; ++it) {
|
|
|
|
(*it)->deiconify(True, False);
|
|
|
|
}
|
|
|
|
}
|
2002-04-11 03:20:38 +00:00
|
|
|
|
2002-06-29 23:50:04 +00:00
|
|
|
if (doraise)
|
|
|
|
raise();
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
void BlackboxWindow::raise(void) {
|
|
|
|
screen->getWorkspace(blackbox_attrib.workspace)->raiseWindow(this);
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
void BlackboxWindow::lower(void) {
|
|
|
|
screen->getWorkspace(blackbox_attrib.workspace)->lowerWindow(this);
|
2002-04-11 03:20:38 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
|
2002-05-25 00:29:44 +00:00
|
|
|
void BlackboxWindow::close(void) {
|
2002-04-11 03:20:38 +00:00
|
|
|
XEvent ce;
|
|
|
|
ce.xclient.type = ClientMessage;
|
2002-06-21 20:40:14 +00:00
|
|
|
ce.xclient.message_type = xatom->getAtom(XAtom::wm_protocols);
|
2002-05-25 00:29:44 +00:00
|
|
|
ce.xclient.display = blackbox->getXDisplay();
|
2002-04-11 03:20:38 +00:00
|
|
|
ce.xclient.window = client.window;
|
|
|
|
ce.xclient.format = 32;
|
2002-06-21 20:40:14 +00:00
|
|
|
ce.xclient.data.l[0] = xatom->getAtom(XAtom::wm_delete_window);
|
2002-04-11 03:20:38 +00:00
|
|
|
ce.xclient.data.l[1] = CurrentTime;
|
|
|
|
ce.xclient.data.l[2] = 0l;
|
|
|
|
ce.xclient.data.l[3] = 0l;
|
|
|
|
ce.xclient.data.l[4] = 0l;
|
2002-05-25 00:29:44 +00:00
|
|
|
XSendEvent(blackbox->getXDisplay(), client.window, False, NoEventMask, &ce);
|
2002-04-11 03:20:38 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
|
2002-05-25 00:29:44 +00:00
|
|
|
void BlackboxWindow::withdraw(void) {
|
2002-06-21 20:40:14 +00:00
|
|
|
// We don't need to worry about resizing because resizing always grabs the X
|
|
|
|
// server. This should only ever happen if using opaque moving.
|
|
|
|
if (flags.moving)
|
|
|
|
endMove();
|
|
|
|
|
2002-04-11 03:20:38 +00:00
|
|
|
flags.visible = False;
|
|
|
|
flags.iconic = False;
|
|
|
|
|
2002-06-21 20:40:14 +00:00
|
|
|
setState(current_state);
|
|
|
|
|
2002-05-25 00:29:44 +00:00
|
|
|
XUnmapWindow(blackbox->getXDisplay(), frame.window);
|
2002-04-11 03:20:38 +00:00
|
|
|
|
2002-05-25 00:29:44 +00:00
|
|
|
XGrabServer(blackbox->getXDisplay());
|
2002-06-21 01:06:29 +00:00
|
|
|
|
2002-05-25 00:29:44 +00:00
|
|
|
XSelectInput(blackbox->getXDisplay(), client.window, NoEventMask);
|
|
|
|
XUnmapWindow(blackbox->getXDisplay(), client.window);
|
|
|
|
XSelectInput(blackbox->getXDisplay(), client.window,
|
|
|
|
PropertyChangeMask | FocusChangeMask | StructureNotifyMask);
|
2002-06-21 01:06:29 +00:00
|
|
|
|
|
|
|
XUngrabServer(blackbox->getXDisplay());
|
2002-04-11 03:20:38 +00:00
|
|
|
|
|
|
|
if (windowmenu) windowmenu->hide();
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2002-05-25 00:29:44 +00:00
|
|
|
void BlackboxWindow::maximize(unsigned int button) {
|
2002-06-21 20:40:14 +00:00
|
|
|
// We don't need to worry about resizing because resizing always grabs the X
|
|
|
|
// server. This should only ever happen if using opaque moving.
|
|
|
|
if (flags.moving)
|
|
|
|
endMove();
|
|
|
|
|
2002-04-11 03:20:38 +00:00
|
|
|
// handle case where menu is open then the max button is used instead
|
|
|
|
if (windowmenu && windowmenu->isVisible()) windowmenu->hide();
|
|
|
|
|
|
|
|
if (flags.maximized) {
|
|
|
|
flags.maximized = 0;
|
|
|
|
|
2002-05-25 00:29:44 +00:00
|
|
|
blackbox_attrib.flags &= ! (AttribMaxHoriz | AttribMaxVert);
|
|
|
|
blackbox_attrib.attrib &= ! (AttribMaxHoriz | AttribMaxVert);
|
2002-04-11 03:20:38 +00:00
|
|
|
|
2002-05-25 15:45:09 +00:00
|
|
|
/*
|
2002-06-21 20:40:14 +00:00
|
|
|
when a resize finishes, maximize(0) is called to clear any maximization
|
2002-05-25 15:45:09 +00:00
|
|
|
flags currently set. Otherwise it still thinks it is maximized.
|
|
|
|
so we do not need to call configure() because resizing will handle it
|
|
|
|
*/
|
2002-05-26 20:25:38 +00:00
|
|
|
if (! flags.resizing)
|
2002-05-25 00:29:44 +00:00
|
|
|
configure(blackbox_attrib.premax_x, blackbox_attrib.premax_y,
|
|
|
|
blackbox_attrib.premax_w, blackbox_attrib.premax_h);
|
2002-04-11 03:20:38 +00:00
|
|
|
|
2002-05-25 00:29:44 +00:00
|
|
|
blackbox_attrib.premax_x = blackbox_attrib.premax_y = 0;
|
|
|
|
blackbox_attrib.premax_w = blackbox_attrib.premax_h = 0;
|
2002-04-11 03:20:38 +00:00
|
|
|
|
2002-05-25 00:29:44 +00:00
|
|
|
redrawAllButtons();
|
2002-04-11 03:20:38 +00:00
|
|
|
setState(current_state);
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
2002-05-25 00:29:44 +00:00
|
|
|
blackbox_attrib.premax_x = frame.rect.x();
|
|
|
|
blackbox_attrib.premax_y = frame.rect.y();
|
|
|
|
blackbox_attrib.premax_w = frame.rect.width();
|
2002-05-28 09:53:11 +00:00
|
|
|
// use client.rect so that clients can be restored even if shaded
|
|
|
|
blackbox_attrib.premax_h =
|
|
|
|
client.rect.height() + frame.margin.top + frame.margin.bottom;
|
2002-04-11 03:20:38 +00:00
|
|
|
|
2002-05-25 00:29:44 +00:00
|
|
|
const Rect &screen_area = screen->availableArea();
|
|
|
|
frame.changing = screen_area;
|
|
|
|
constrain(TopLeft);
|
2002-04-11 03:20:38 +00:00
|
|
|
|
|
|
|
switch(button) {
|
|
|
|
case 1:
|
2002-05-25 00:29:44 +00:00
|
|
|
blackbox_attrib.flags |= AttribMaxHoriz | AttribMaxVert;
|
|
|
|
blackbox_attrib.attrib |= AttribMaxHoriz | AttribMaxVert;
|
2002-04-11 03:20:38 +00:00
|
|
|
break;
|
|
|
|
|
|
|
|
case 2:
|
2002-05-25 00:29:44 +00:00
|
|
|
blackbox_attrib.flags |= AttribMaxVert;
|
|
|
|
blackbox_attrib.attrib |= AttribMaxVert;
|
2002-04-11 03:20:38 +00:00
|
|
|
|
2002-05-25 00:29:44 +00:00
|
|
|
frame.changing.setX(frame.rect.x());
|
|
|
|
frame.changing.setWidth(frame.rect.width());
|
2002-04-11 03:20:38 +00:00
|
|
|
break;
|
|
|
|
|
|
|
|
case 3:
|
2002-05-25 00:29:44 +00:00
|
|
|
blackbox_attrib.flags |= AttribMaxHoriz;
|
|
|
|
blackbox_attrib.attrib |= AttribMaxHoriz;
|
2002-04-11 03:20:38 +00:00
|
|
|
|
2002-05-25 00:29:44 +00:00
|
|
|
frame.changing.setY(frame.rect.y());
|
|
|
|
frame.changing.setHeight(frame.rect.height());
|
2002-04-11 03:20:38 +00:00
|
|
|
break;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (flags.shaded) {
|
2002-05-25 00:29:44 +00:00
|
|
|
blackbox_attrib.flags ^= AttribShaded;
|
|
|
|
blackbox_attrib.attrib ^= AttribShaded;
|
2002-04-11 03:20:38 +00:00
|
|
|
flags.shaded = False;
|
|
|
|
}
|
|
|
|
|
|
|
|
flags.maximized = button;
|
|
|
|
|
2002-05-25 00:29:44 +00:00
|
|
|
configure(frame.changing.x(), frame.changing.y(),
|
|
|
|
frame.changing.width(), frame.changing.height());
|
2002-05-25 15:45:09 +00:00
|
|
|
if (flags.focused)
|
2002-06-29 23:50:04 +00:00
|
|
|
raise();
|
2002-05-25 00:29:44 +00:00
|
|
|
redrawAllButtons();
|
2002-04-11 03:20:38 +00:00
|
|
|
setState(current_state);
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2002-05-25 00:29:44 +00:00
|
|
|
// re-maximizes the window to take into account availableArea changes
|
|
|
|
void BlackboxWindow::remaximize(void) {
|
|
|
|
// save the original dimensions because maximize will wipe them out
|
|
|
|
int premax_x = blackbox_attrib.premax_x,
|
|
|
|
premax_y = blackbox_attrib.premax_y,
|
|
|
|
premax_w = blackbox_attrib.premax_w,
|
|
|
|
premax_h = blackbox_attrib.premax_h;
|
2002-04-11 03:20:38 +00:00
|
|
|
|
2002-05-25 00:29:44 +00:00
|
|
|
unsigned int button = flags.maximized;
|
|
|
|
flags.maximized = 0; // trick maximize() into working
|
|
|
|
maximize(button);
|
|
|
|
|
|
|
|
// restore saved values
|
|
|
|
blackbox_attrib.premax_x = premax_x;
|
|
|
|
blackbox_attrib.premax_y = premax_y;
|
|
|
|
blackbox_attrib.premax_w = premax_w;
|
|
|
|
blackbox_attrib.premax_h = premax_h;
|
2002-04-11 03:20:38 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
|
2002-05-25 00:29:44 +00:00
|
|
|
void BlackboxWindow::setWorkspace(unsigned int n) {
|
|
|
|
blackbox_attrib.flags |= AttribWorkspace;
|
|
|
|
blackbox_attrib.workspace = n;
|
2002-06-21 20:40:14 +00:00
|
|
|
xatom->setValue(client.window, XAtom::net_wm_desktop, XAtom::cardinal, n);
|
2002-05-25 00:29:44 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
void BlackboxWindow::shade(void) {
|
2002-04-11 03:20:38 +00:00
|
|
|
if (flags.shaded) {
|
2002-05-25 00:29:44 +00:00
|
|
|
XResizeWindow(blackbox->getXDisplay(), frame.window,
|
|
|
|
frame.inside_w, frame.inside_h);
|
2002-04-11 03:20:38 +00:00
|
|
|
flags.shaded = False;
|
2002-05-25 00:29:44 +00:00
|
|
|
blackbox_attrib.flags ^= AttribShaded;
|
|
|
|
blackbox_attrib.attrib ^= AttribShaded;
|
2002-04-11 03:20:38 +00:00
|
|
|
|
|
|
|
setState(NormalState);
|
2002-05-25 00:29:44 +00:00
|
|
|
|
|
|
|
// set the frame rect to the normal size
|
|
|
|
frame.rect.setHeight(client.rect.height() + frame.margin.top +
|
|
|
|
frame.margin.bottom);
|
2002-04-11 03:20:38 +00:00
|
|
|
} else {
|
2002-05-26 20:53:48 +00:00
|
|
|
if (! (decorations & Decor_Titlebar))
|
|
|
|
return;
|
|
|
|
|
2002-05-25 00:29:44 +00:00
|
|
|
XResizeWindow(blackbox->getXDisplay(), frame.window,
|
|
|
|
frame.inside_w, frame.title_h);
|
2002-04-11 03:20:38 +00:00
|
|
|
flags.shaded = True;
|
2002-05-25 00:29:44 +00:00
|
|
|
blackbox_attrib.flags |= AttribShaded;
|
|
|
|
blackbox_attrib.attrib |= AttribShaded;
|
2002-04-11 03:20:38 +00:00
|
|
|
|
|
|
|
setState(IconicState);
|
2002-05-25 00:29:44 +00:00
|
|
|
|
|
|
|
// set the frame rect to the shaded size
|
|
|
|
frame.rect.setHeight(frame.title_h + (frame.border_w * 2));
|
2002-04-11 03:20:38 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2002-06-21 20:40:14 +00:00
|
|
|
/*
|
|
|
|
* (Un)Sticks a window and its relatives.
|
|
|
|
*/
|
2002-05-25 00:29:44 +00:00
|
|
|
void BlackboxWindow::stick(void) {
|
2002-04-11 03:20:38 +00:00
|
|
|
if (flags.stuck) {
|
2002-05-25 00:29:44 +00:00
|
|
|
blackbox_attrib.flags ^= AttribOmnipresent;
|
|
|
|
blackbox_attrib.attrib ^= AttribOmnipresent;
|
2002-04-11 03:20:38 +00:00
|
|
|
|
|
|
|
flags.stuck = False;
|
|
|
|
|
|
|
|
if (! flags.iconic)
|
2002-05-25 00:29:44 +00:00
|
|
|
screen->reassociateWindow(this, BSENTINEL, True);
|
2002-06-21 20:40:14 +00:00
|
|
|
else
|
|
|
|
// temporary fix since sticky windows suck. set the hint to what we
|
|
|
|
// actually hold in our data.
|
|
|
|
xatom->setValue(client.window, XAtom::net_wm_desktop, XAtom::cardinal,
|
|
|
|
blackbox_attrib.workspace);
|
2002-04-11 03:20:38 +00:00
|
|
|
|
|
|
|
setState(current_state);
|
|
|
|
} else {
|
|
|
|
flags.stuck = True;
|
|
|
|
|
2002-05-25 00:29:44 +00:00
|
|
|
blackbox_attrib.flags |= AttribOmnipresent;
|
|
|
|
blackbox_attrib.attrib |= AttribOmnipresent;
|
2002-04-11 03:20:38 +00:00
|
|
|
|
2002-06-21 20:40:14 +00:00
|
|
|
// temporary fix since sticky windows suck. set the hint to a different
|
|
|
|
// value than that contained in the class' data.
|
|
|
|
xatom->setValue(client.window, XAtom::net_wm_desktop, XAtom::cardinal,
|
|
|
|
0xffffffff);
|
|
|
|
|
2002-04-11 03:20:38 +00:00
|
|
|
setState(current_state);
|
|
|
|
}
|
2002-06-21 20:40:14 +00:00
|
|
|
// go up the chain
|
|
|
|
if (isTransient() && client.transient_for != (BlackboxWindow *) ~0ul &&
|
|
|
|
client.transient_for->isStuck() != flags.stuck)
|
|
|
|
client.transient_for->stick();
|
|
|
|
// go down the chain
|
|
|
|
BlackboxWindowList::iterator it;
|
|
|
|
const BlackboxWindowList::iterator end = client.transientList.end();
|
|
|
|
for (it = client.transientList.begin(); it != end; ++it)
|
|
|
|
if ((*it)->isStuck() != flags.stuck)
|
|
|
|
(*it)->stick();
|
2002-04-11 03:20:38 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
|
2002-05-25 00:29:44 +00:00
|
|
|
void BlackboxWindow::setFocusFlag(bool focus) {
|
2002-06-21 01:06:29 +00:00
|
|
|
// only focus a window if it is visible
|
|
|
|
if (focus && !flags.visible)
|
|
|
|
return;
|
|
|
|
|
2002-04-11 03:20:38 +00:00
|
|
|
flags.focused = focus;
|
|
|
|
|
2002-05-25 00:29:44 +00:00
|
|
|
if (decorations & Decor_Titlebar) {
|
2002-04-11 03:20:38 +00:00
|
|
|
if (flags.focused) {
|
|
|
|
if (frame.ftitle)
|
2002-05-25 00:29:44 +00:00
|
|
|
XSetWindowBackgroundPixmap(blackbox->getXDisplay(),
|
|
|
|
frame.title, frame.ftitle);
|
2002-04-11 03:20:38 +00:00
|
|
|
else
|
2002-05-25 00:29:44 +00:00
|
|
|
XSetWindowBackground(blackbox->getXDisplay(),
|
|
|
|
frame.title, frame.ftitle_pixel);
|
2002-04-11 03:20:38 +00:00
|
|
|
} else {
|
|
|
|
if (frame.utitle)
|
2002-05-25 00:29:44 +00:00
|
|
|
XSetWindowBackgroundPixmap(blackbox->getXDisplay(),
|
|
|
|
frame.title, frame.utitle);
|
2002-04-11 03:20:38 +00:00
|
|
|
else
|
2002-05-25 00:29:44 +00:00
|
|
|
XSetWindowBackground(blackbox->getXDisplay(),
|
|
|
|
frame.title, frame.utitle_pixel);
|
2002-04-11 03:20:38 +00:00
|
|
|
}
|
2002-05-25 00:29:44 +00:00
|
|
|
XClearWindow(blackbox->getXDisplay(), frame.title);
|
2002-04-11 03:20:38 +00:00
|
|
|
|
|
|
|
redrawLabel();
|
|
|
|
redrawAllButtons();
|
|
|
|
}
|
|
|
|
|
2002-05-25 00:29:44 +00:00
|
|
|
if (decorations & Decor_Handle) {
|
2002-04-11 03:20:38 +00:00
|
|
|
if (flags.focused) {
|
|
|
|
if (frame.fhandle)
|
2002-05-25 00:29:44 +00:00
|
|
|
XSetWindowBackgroundPixmap(blackbox->getXDisplay(),
|
|
|
|
frame.handle, frame.fhandle);
|
2002-04-11 03:20:38 +00:00
|
|
|
else
|
2002-05-25 00:29:44 +00:00
|
|
|
XSetWindowBackground(blackbox->getXDisplay(),
|
|
|
|
frame.handle, frame.fhandle_pixel);
|
2002-04-11 03:20:38 +00:00
|
|
|
|
|
|
|
if (frame.fgrip) {
|
2002-05-25 00:29:44 +00:00
|
|
|
XSetWindowBackgroundPixmap(blackbox->getXDisplay(),
|
|
|
|
frame.left_grip, frame.fgrip);
|
|
|
|
XSetWindowBackgroundPixmap(blackbox->getXDisplay(),
|
|
|
|
frame.right_grip, frame.fgrip);
|
2002-04-11 03:20:38 +00:00
|
|
|
} else {
|
2002-05-25 00:29:44 +00:00
|
|
|
XSetWindowBackground(blackbox->getXDisplay(),
|
|
|
|
frame.left_grip, frame.fgrip_pixel);
|
|
|
|
XSetWindowBackground(blackbox->getXDisplay(),
|
|
|
|
frame.right_grip, frame.fgrip_pixel);
|
2002-04-11 03:20:38 +00:00
|
|
|
}
|
|
|
|
} else {
|
|
|
|
if (frame.uhandle)
|
2002-05-25 00:29:44 +00:00
|
|
|
XSetWindowBackgroundPixmap(blackbox->getXDisplay(),
|
|
|
|
frame.handle, frame.uhandle);
|
2002-04-11 03:20:38 +00:00
|
|
|
else
|
2002-05-25 00:29:44 +00:00
|
|
|
XSetWindowBackground(blackbox->getXDisplay(),
|
|
|
|
frame.handle, frame.uhandle_pixel);
|
2002-04-11 03:20:38 +00:00
|
|
|
|
|
|
|
if (frame.ugrip) {
|
2002-05-25 00:29:44 +00:00
|
|
|
XSetWindowBackgroundPixmap(blackbox->getXDisplay(),
|
|
|
|
frame.left_grip, frame.ugrip);
|
|
|
|
XSetWindowBackgroundPixmap(blackbox->getXDisplay(),
|
|
|
|
frame.right_grip, frame.ugrip);
|
2002-04-11 03:20:38 +00:00
|
|
|
} else {
|
2002-05-25 00:29:44 +00:00
|
|
|
XSetWindowBackground(blackbox->getXDisplay(),
|
|
|
|
frame.left_grip, frame.ugrip_pixel);
|
|
|
|
XSetWindowBackground(blackbox->getXDisplay(),
|
|
|
|
frame.right_grip, frame.ugrip_pixel);
|
2002-04-11 03:20:38 +00:00
|
|
|
}
|
|
|
|
}
|
2002-05-25 00:29:44 +00:00
|
|
|
XClearWindow(blackbox->getXDisplay(), frame.handle);
|
|
|
|
XClearWindow(blackbox->getXDisplay(), frame.left_grip);
|
|
|
|
XClearWindow(blackbox->getXDisplay(), frame.right_grip);
|
2002-04-11 03:20:38 +00:00
|
|
|
}
|
|
|
|
|
2002-05-25 00:29:44 +00:00
|
|
|
if (decorations & Decor_Border) {
|
2002-04-11 03:20:38 +00:00
|
|
|
if (flags.focused)
|
2002-05-25 00:29:44 +00:00
|
|
|
XSetWindowBorder(blackbox->getXDisplay(),
|
|
|
|
frame.plate, frame.fborder_pixel);
|
2002-04-11 03:20:38 +00:00
|
|
|
else
|
2002-05-25 00:29:44 +00:00
|
|
|
XSetWindowBorder(blackbox->getXDisplay(),
|
|
|
|
frame.plate, frame.uborder_pixel);
|
2002-04-11 03:20:38 +00:00
|
|
|
}
|
|
|
|
|
2002-05-25 00:29:44 +00:00
|
|
|
if (screen->isSloppyFocus() && screen->doAutoRaise()) {
|
|
|
|
if (isFocused()) timer->start();
|
|
|
|
else timer->stop();
|
|
|
|
}
|
2002-04-28 19:09:25 +00:00
|
|
|
|
2002-05-25 00:29:44 +00:00
|
|
|
if (isFocused())
|
|
|
|
blackbox->setFocusedWindow(this);
|
2002-04-11 03:20:38 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
|
2002-05-25 00:29:44 +00:00
|
|
|
void BlackboxWindow::installColormap(bool install) {
|
2002-04-11 03:20:38 +00:00
|
|
|
int i = 0, ncmap = 0;
|
2002-05-25 00:29:44 +00:00
|
|
|
Colormap *cmaps = XListInstalledColormaps(blackbox->getXDisplay(),
|
|
|
|
client.window, &ncmap);
|
2002-04-11 03:20:38 +00:00
|
|
|
XWindowAttributes wattrib;
|
|
|
|
if (cmaps) {
|
2002-05-25 00:29:44 +00:00
|
|
|
if (XGetWindowAttributes(blackbox->getXDisplay(),
|
|
|
|
client.window, &wattrib)) {
|
2002-04-11 03:20:38 +00:00
|
|
|
if (install) {
|
2002-05-16 22:35:59 +00:00
|
|
|
// install the window's colormap
|
|
|
|
for (i = 0; i < ncmap; i++) {
|
|
|
|
if (*(cmaps + i) == wattrib.colormap)
|
|
|
|
// this window is using an installed color map... do not install
|
|
|
|
install = False;
|
|
|
|
}
|
|
|
|
// otherwise, install the window's colormap
|
|
|
|
if (install)
|
2002-05-25 00:29:44 +00:00
|
|
|
XInstallColormap(blackbox->getXDisplay(), wattrib.colormap);
|
2002-04-11 03:20:38 +00:00
|
|
|
} else {
|
2002-05-16 22:35:59 +00:00
|
|
|
// uninstall the window's colormap
|
|
|
|
for (i = 0; i < ncmap; i++) {
|
|
|
|
if (*(cmaps + i) == wattrib.colormap)
|
|
|
|
// we found the colormap to uninstall
|
2002-05-25 00:29:44 +00:00
|
|
|
XUninstallColormap(blackbox->getXDisplay(), wattrib.colormap);
|
2002-05-16 22:35:59 +00:00
|
|
|
}
|
2002-04-11 03:20:38 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
XFree(cmaps);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2002-06-21 20:40:14 +00:00
|
|
|
void BlackboxWindow::setAllowedActions(void) {
|
|
|
|
Atom actions[7];
|
|
|
|
int num = 0;
|
|
|
|
|
|
|
|
actions[num++] = xatom->getAtom(XAtom::net_wm_action_shade);
|
|
|
|
actions[num++] = xatom->getAtom(XAtom::net_wm_action_change_desktop);
|
|
|
|
actions[num++] = xatom->getAtom(XAtom::net_wm_action_close);
|
|
|
|
|
|
|
|
if (functions & Func_Move)
|
|
|
|
actions[num++] = xatom->getAtom(XAtom::net_wm_action_move);
|
|
|
|
if (functions & Func_Resize)
|
|
|
|
actions[num++] = xatom->getAtom(XAtom::net_wm_action_resize);
|
|
|
|
if (functions & Func_Maximize) {
|
|
|
|
actions[num++] = xatom->getAtom(XAtom::net_wm_action_maximize_horz);
|
|
|
|
actions[num++] = xatom->getAtom(XAtom::net_wm_action_maximize_vert);
|
|
|
|
}
|
|
|
|
|
|
|
|
xatom->setValue(client.window, XAtom::net_wm_allowed_actions, XAtom::atom,
|
|
|
|
actions, num);
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2002-05-25 00:29:44 +00:00
|
|
|
void BlackboxWindow::setState(unsigned long new_state) {
|
2002-04-11 03:20:38 +00:00
|
|
|
current_state = new_state;
|
|
|
|
|
|
|
|
unsigned long state[2];
|
2002-05-25 00:29:44 +00:00
|
|
|
state[0] = current_state;
|
|
|
|
state[1] = None;
|
2002-05-30 06:51:43 +00:00
|
|
|
xatom->setValue(client.window, XAtom::wm_state, XAtom::wm_state, state, 2);
|
|
|
|
|
|
|
|
xatom->setValue(client.window, XAtom::blackbox_attributes,
|
|
|
|
XAtom::blackbox_attributes, (unsigned long *)&blackbox_attrib,
|
2002-05-25 00:29:44 +00:00
|
|
|
PropBlackboxAttributesElements);
|
2002-06-21 20:40:14 +00:00
|
|
|
|
|
|
|
Atom netstate[8];
|
|
|
|
int num = 0;
|
|
|
|
if (flags.modal)
|
|
|
|
netstate[num++] = xatom->getAtom(XAtom::net_wm_state_modal);
|
|
|
|
if (flags.shaded)
|
|
|
|
netstate[num++] = xatom->getAtom(XAtom::net_wm_state_shaded);
|
|
|
|
if (flags.iconic)
|
|
|
|
netstate[num++] = xatom->getAtom(XAtom::net_wm_state_hidden);
|
|
|
|
if (flags.skip_taskbar)
|
|
|
|
netstate[num++] = xatom->getAtom(XAtom::net_wm_state_skip_taskbar);
|
|
|
|
if (flags.skip_pager)
|
|
|
|
netstate[num++] = xatom->getAtom(XAtom::net_wm_state_skip_pager);
|
|
|
|
if (flags.fullscreen)
|
|
|
|
netstate[num++] = xatom->getAtom(XAtom::net_wm_state_fullscreen);
|
|
|
|
if (flags.maximized == 1 || flags.maximized == 2)
|
|
|
|
netstate[num++] = xatom->getAtom(XAtom::net_wm_state_maximized_vert);
|
|
|
|
if (flags.maximized == 1 || flags.maximized == 3)
|
|
|
|
netstate[num++] = xatom->getAtom(XAtom::net_wm_state_maximized_horz);
|
|
|
|
xatom->setValue(client.window, XAtom::net_wm_state, XAtom::atom,
|
|
|
|
netstate, num);
|
2002-04-11 03:20:38 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
|
2002-05-25 00:29:44 +00:00
|
|
|
bool BlackboxWindow::getState(void) {
|
2002-06-21 20:40:14 +00:00
|
|
|
bool ret = xatom->getValue(client.window, XAtom::wm_state, XAtom::wm_state,
|
|
|
|
current_state);
|
|
|
|
if (! ret) current_state = 0;
|
|
|
|
return ret;
|
2002-04-11 03:20:38 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
|
2002-05-25 00:29:44 +00:00
|
|
|
void BlackboxWindow::restoreAttributes(void) {
|
2002-06-21 20:40:14 +00:00
|
|
|
unsigned long num = PropBlackboxAttributesElements;
|
2002-05-25 00:29:44 +00:00
|
|
|
BlackboxAttributes *net;
|
2002-06-21 20:40:14 +00:00
|
|
|
if (! xatom->getValue(client.window, XAtom::blackbox_attributes,
|
|
|
|
XAtom::blackbox_attributes, num,
|
|
|
|
(unsigned long **)&net))
|
|
|
|
return;
|
|
|
|
if (num < PropBlackboxAttributesElements) {
|
|
|
|
delete net;
|
2002-04-11 03:20:38 +00:00
|
|
|
return;
|
2002-06-21 20:40:14 +00:00
|
|
|
}
|
2002-04-11 03:20:38 +00:00
|
|
|
|
2002-06-21 01:06:29 +00:00
|
|
|
if (net->flags & AttribShaded && net->attrib & AttribShaded) {
|
2002-04-11 03:20:38 +00:00
|
|
|
flags.shaded = False;
|
|
|
|
shade();
|
|
|
|
|
2002-06-21 01:06:29 +00:00
|
|
|
/*
|
|
|
|
Because the iconic'ness of shaded windows is lost, we need to set the
|
|
|
|
state to NormalState so that shaded windows on other workspaces will not
|
|
|
|
get shown on the first workspace.
|
|
|
|
At this point in the life of a window, current_state should only be set
|
|
|
|
to IconicState if the window was an *icon*, not if it was shaded.
|
|
|
|
*/
|
|
|
|
current_state = NormalState;
|
|
|
|
}
|
2002-04-11 03:20:38 +00:00
|
|
|
|
2002-05-25 00:29:44 +00:00
|
|
|
if ((net->workspace != screen->getCurrentWorkspaceID()) &&
|
2002-06-21 20:40:14 +00:00
|
|
|
(net->workspace < screen->getWorkspaceCount()))
|
2002-05-25 00:29:44 +00:00
|
|
|
screen->reassociateWindow(this, net->workspace, True);
|
2002-04-11 03:20:38 +00:00
|
|
|
|
2002-06-21 20:40:14 +00:00
|
|
|
if ((blackbox_attrib.workspace != screen->getCurrentWorkspaceID()) &&
|
|
|
|
(blackbox_attrib.workspace < screen->getWorkspaceCount())) {
|
2002-06-21 01:06:29 +00:00
|
|
|
// set to WithdrawnState so it will be mapped on the new workspace
|
2002-04-11 03:20:38 +00:00
|
|
|
if (current_state == NormalState) current_state = WithdrawnState;
|
|
|
|
} else if (current_state == WithdrawnState) {
|
2002-06-21 01:06:29 +00:00
|
|
|
// the window is on this workspace and is Withdrawn, so it is waiting to
|
|
|
|
// be mapped
|
2002-04-11 03:20:38 +00:00
|
|
|
current_state = NormalState;
|
|
|
|
}
|
|
|
|
|
2002-06-21 01:06:29 +00:00
|
|
|
if (net->flags & AttribOmnipresent && net->attrib & AttribOmnipresent) {
|
2002-04-11 03:20:38 +00:00
|
|
|
flags.stuck = False;
|
|
|
|
stick();
|
|
|
|
|
2002-06-21 01:06:29 +00:00
|
|
|
// if the window was on another workspace, it was going to be hidden. this
|
|
|
|
// specifies that the window should be mapped since it is sticky.
|
|
|
|
if (current_state == WithdrawnState) current_state = NormalState;
|
2002-04-11 03:20:38 +00:00
|
|
|
}
|
|
|
|
|
2002-06-21 01:06:29 +00:00
|
|
|
if (net->flags & AttribMaxHoriz || net->flags & AttribMaxVert) {
|
2002-05-25 00:29:44 +00:00
|
|
|
int x = net->premax_x, y = net->premax_y;
|
|
|
|
unsigned int w = net->premax_w, h = net->premax_h;
|
2002-04-11 03:20:38 +00:00
|
|
|
flags.maximized = 0;
|
|
|
|
|
2002-05-25 00:29:44 +00:00
|
|
|
unsigned int m = 0;
|
|
|
|
if ((net->flags & AttribMaxHoriz) &&
|
|
|
|
(net->flags & AttribMaxVert))
|
|
|
|
m = (net->attrib & (AttribMaxHoriz | AttribMaxVert)) ? 1 : 0;
|
|
|
|
else if (net->flags & AttribMaxVert)
|
|
|
|
m = (net->attrib & AttribMaxVert) ? 2 : 0;
|
|
|
|
else if (net->flags & AttribMaxHoriz)
|
|
|
|
m = (net->attrib & AttribMaxHoriz) ? 3 : 0;
|
2002-04-11 03:20:38 +00:00
|
|
|
|
|
|
|
if (m) maximize(m);
|
|
|
|
|
2002-05-25 00:29:44 +00:00
|
|
|
blackbox_attrib.premax_x = x;
|
|
|
|
blackbox_attrib.premax_y = y;
|
|
|
|
blackbox_attrib.premax_w = w;
|
|
|
|
blackbox_attrib.premax_h = h;
|
2002-04-11 03:20:38 +00:00
|
|
|
}
|
|
|
|
|
2002-06-21 01:06:29 +00:00
|
|
|
// with the state set it will then be the map events job to read the window's
|
|
|
|
// state and behave accordingly
|
2002-05-25 00:29:44 +00:00
|
|
|
|
2002-06-21 20:40:14 +00:00
|
|
|
delete net;
|
2002-05-25 00:29:44 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
/*
|
|
|
|
* Positions the frame according the the client window position and window
|
|
|
|
* gravity.
|
|
|
|
*/
|
|
|
|
void BlackboxWindow::setGravityOffsets(void) {
|
|
|
|
// x coordinates for each gravity type
|
|
|
|
const int x_west = client.rect.x();
|
|
|
|
const int x_east = client.rect.right() - frame.inside_w + 1;
|
2002-05-30 04:35:22 +00:00
|
|
|
const int x_center = client.rect.left() +
|
|
|
|
((client.rect.width() - frame.rect.width()) / 2);
|
2002-05-25 00:29:44 +00:00
|
|
|
// y coordinates for each gravity type
|
|
|
|
const int y_north = client.rect.y();
|
|
|
|
const int y_south = client.rect.bottom() - frame.inside_h + 1;
|
2002-05-30 04:35:22 +00:00
|
|
|
const int y_center = client.rect.top() +
|
|
|
|
((client.rect.height() - frame.rect.height()) / 2);
|
2002-05-25 00:29:44 +00:00
|
|
|
|
|
|
|
switch (client.win_gravity) {
|
|
|
|
default:
|
|
|
|
case NorthWestGravity: frame.rect.setPos(x_west, y_north); break;
|
|
|
|
case NorthGravity: frame.rect.setPos(x_center, y_north); break;
|
|
|
|
case NorthEastGravity: frame.rect.setPos(x_east, y_north); break;
|
|
|
|
case SouthWestGravity: frame.rect.setPos(x_west, y_south); break;
|
|
|
|
case SouthGravity: frame.rect.setPos(x_center, y_south); break;
|
|
|
|
case SouthEastGravity: frame.rect.setPos(x_east, y_south); break;
|
|
|
|
case WestGravity: frame.rect.setPos(x_west, y_center); break;
|
|
|
|
case CenterGravity: frame.rect.setPos(x_center, y_center); break;
|
|
|
|
case EastGravity: frame.rect.setPos(x_east, y_center); break;
|
|
|
|
|
|
|
|
case ForgetGravity:
|
|
|
|
case StaticGravity:
|
|
|
|
frame.rect.setPos(client.rect.x() - frame.margin.left,
|
|
|
|
client.rect.y() - frame.margin.top);
|
|
|
|
break;
|
|
|
|
}
|
2002-04-11 03:20:38 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
/*
|
|
|
|
* The reverse of the setGravityOffsets function. Uses the frame window's
|
|
|
|
* position to find the window's reference point.
|
|
|
|
*/
|
2002-05-25 00:29:44 +00:00
|
|
|
void BlackboxWindow::restoreGravity(void) {
|
2002-04-11 03:20:38 +00:00
|
|
|
// x coordinates for each gravity type
|
2002-05-25 00:29:44 +00:00
|
|
|
const int x_west = frame.rect.x();
|
|
|
|
const int x_east = frame.rect.x() + frame.inside_w - client.rect.width();
|
2002-05-30 04:35:22 +00:00
|
|
|
const int x_center = frame.rect.x() -
|
|
|
|
((client.rect.width() - frame.rect.width()) / 2);
|
2002-04-11 03:20:38 +00:00
|
|
|
// y coordinates for each gravity type
|
2002-05-25 00:29:44 +00:00
|
|
|
const int y_north = frame.rect.y();
|
|
|
|
const int y_south = frame.rect.y() + frame.inside_h - client.rect.height();
|
2002-05-30 04:35:22 +00:00
|
|
|
const int y_center = frame.rect.y() -
|
|
|
|
((client.rect.height() - frame.rect.height()) / 2);
|
2002-04-11 03:20:38 +00:00
|
|
|
|
|
|
|
switch(client.win_gravity) {
|
|
|
|
default:
|
2002-05-25 00:29:44 +00:00
|
|
|
case NorthWestGravity: client.rect.setPos(x_west, y_north); break;
|
|
|
|
case NorthGravity: client.rect.setPos(x_center, y_north); break;
|
|
|
|
case NorthEastGravity: client.rect.setPos(x_east, y_north); break;
|
|
|
|
case SouthWestGravity: client.rect.setPos(x_west, y_south); break;
|
|
|
|
case SouthGravity: client.rect.setPos(x_center, y_south); break;
|
|
|
|
case SouthEastGravity: client.rect.setPos(x_east, y_south); break;
|
|
|
|
case WestGravity: client.rect.setPos(x_west, y_center); break;
|
|
|
|
case CenterGravity: client.rect.setPos(x_center, y_center); break;
|
|
|
|
case EastGravity: client.rect.setPos(x_east, y_center); break;
|
|
|
|
|
2002-04-11 03:20:38 +00:00
|
|
|
case ForgetGravity:
|
|
|
|
case StaticGravity:
|
2002-05-25 00:29:44 +00:00
|
|
|
client.rect.setPos(frame.rect.left() + frame.margin.left,
|
|
|
|
frame.rect.top() + frame.margin.top);
|
2002-04-11 03:20:38 +00:00
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2002-05-25 00:29:44 +00:00
|
|
|
void BlackboxWindow::redrawLabel(void) {
|
2002-04-11 03:20:38 +00:00
|
|
|
if (flags.focused) {
|
|
|
|
if (frame.flabel)
|
2002-05-25 00:29:44 +00:00
|
|
|
XSetWindowBackgroundPixmap(blackbox->getXDisplay(),
|
|
|
|
frame.label, frame.flabel);
|
2002-04-11 03:20:38 +00:00
|
|
|
else
|
2002-05-25 00:29:44 +00:00
|
|
|
XSetWindowBackground(blackbox->getXDisplay(),
|
|
|
|
frame.label, frame.flabel_pixel);
|
2002-04-11 03:20:38 +00:00
|
|
|
} else {
|
|
|
|
if (frame.ulabel)
|
2002-05-25 00:29:44 +00:00
|
|
|
XSetWindowBackgroundPixmap(blackbox->getXDisplay(),
|
|
|
|
frame.label, frame.ulabel);
|
2002-04-11 03:20:38 +00:00
|
|
|
else
|
2002-05-25 00:29:44 +00:00
|
|
|
XSetWindowBackground(blackbox->getXDisplay(),
|
|
|
|
frame.label, frame.ulabel_pixel);
|
2002-04-11 03:20:38 +00:00
|
|
|
}
|
2002-05-25 00:29:44 +00:00
|
|
|
XClearWindow(blackbox->getXDisplay(), frame.label);
|
2002-04-11 03:20:38 +00:00
|
|
|
|
2002-05-25 00:29:44 +00:00
|
|
|
WindowStyle *style = screen->getWindowStyle();
|
2002-04-11 03:20:38 +00:00
|
|
|
|
2002-05-25 00:29:44 +00:00
|
|
|
int pos = frame.bevel_w * 2,
|
|
|
|
dlen = style->doJustify(client.title.c_str(), pos, frame.label_w,
|
|
|
|
frame.bevel_w * 4, i18n.multibyte());
|
2002-04-11 03:20:38 +00:00
|
|
|
|
2002-05-25 00:29:44 +00:00
|
|
|
BPen pen((flags.focused) ? style->l_text_focus : style->l_text_unfocus,
|
|
|
|
style->font);
|
2002-05-16 22:35:59 +00:00
|
|
|
if (i18n.multibyte())
|
2002-05-25 00:29:44 +00:00
|
|
|
XmbDrawString(blackbox->getXDisplay(), frame.label, style->fontset,
|
|
|
|
pen.gc(), pos,
|
2002-05-16 22:35:59 +00:00
|
|
|
(1 - style->fontset_extents->max_ink_extent.y),
|
2002-05-25 00:29:44 +00:00
|
|
|
client.title.c_str(), dlen);
|
2002-04-11 03:20:38 +00:00
|
|
|
else
|
2002-05-25 00:29:44 +00:00
|
|
|
XDrawString(blackbox->getXDisplay(), frame.label, pen.gc(), pos,
|
|
|
|
(style->font->ascent + 1), client.title.c_str(), dlen);
|
2002-04-11 03:20:38 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
|
2002-05-25 00:29:44 +00:00
|
|
|
void BlackboxWindow::redrawAllButtons(void) {
|
2002-04-11 03:20:38 +00:00
|
|
|
if (frame.iconify_button) redrawIconifyButton(False);
|
|
|
|
if (frame.maximize_button) redrawMaximizeButton(flags.maximized);
|
|
|
|
if (frame.close_button) redrawCloseButton(False);
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2002-05-25 00:29:44 +00:00
|
|
|
void BlackboxWindow::redrawIconifyButton(bool pressed) {
|
2002-04-11 03:20:38 +00:00
|
|
|
if (! pressed) {
|
|
|
|
if (flags.focused) {
|
|
|
|
if (frame.fbutton)
|
2002-05-25 00:29:44 +00:00
|
|
|
XSetWindowBackgroundPixmap(blackbox->getXDisplay(),
|
|
|
|
frame.iconify_button, frame.fbutton);
|
2002-04-11 03:20:38 +00:00
|
|
|
else
|
2002-05-25 00:29:44 +00:00
|
|
|
XSetWindowBackground(blackbox->getXDisplay(),
|
|
|
|
frame.iconify_button, frame.fbutton_pixel);
|
2002-04-11 03:20:38 +00:00
|
|
|
} else {
|
|
|
|
if (frame.ubutton)
|
2002-05-25 00:29:44 +00:00
|
|
|
XSetWindowBackgroundPixmap(blackbox->getXDisplay(),
|
|
|
|
frame.iconify_button, frame.ubutton);
|
2002-04-11 03:20:38 +00:00
|
|
|
else
|
2002-05-25 00:29:44 +00:00
|
|
|
XSetWindowBackground(blackbox->getXDisplay(), frame.iconify_button,
|
2002-05-16 22:35:59 +00:00
|
|
|
frame.ubutton_pixel);
|
2002-04-11 03:20:38 +00:00
|
|
|
}
|
|
|
|
} else {
|
|
|
|
if (frame.pbutton)
|
2002-05-25 00:29:44 +00:00
|
|
|
XSetWindowBackgroundPixmap(blackbox->getXDisplay(),
|
|
|
|
frame.iconify_button, frame.pbutton);
|
2002-04-11 03:20:38 +00:00
|
|
|
else
|
2002-05-25 00:29:44 +00:00
|
|
|
XSetWindowBackground(blackbox->getXDisplay(),
|
|
|
|
frame.iconify_button, frame.pbutton_pixel);
|
2002-04-11 03:20:38 +00:00
|
|
|
}
|
2002-05-25 00:29:44 +00:00
|
|
|
XClearWindow(blackbox->getXDisplay(), frame.iconify_button);
|
2002-04-11 03:20:38 +00:00
|
|
|
|
2002-05-25 00:29:44 +00:00
|
|
|
BPen pen((flags.focused) ? screen->getWindowStyle()->b_pic_focus :
|
|
|
|
screen->getWindowStyle()->b_pic_unfocus);
|
|
|
|
XDrawRectangle(blackbox->getXDisplay(), frame.iconify_button, pen.gc(),
|
|
|
|
2, (frame.button_w - 5), (frame.button_w - 5), 2);
|
2002-04-11 03:20:38 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
|
2002-05-25 00:29:44 +00:00
|
|
|
void BlackboxWindow::redrawMaximizeButton(bool pressed) {
|
2002-04-11 03:20:38 +00:00
|
|
|
if (! pressed) {
|
|
|
|
if (flags.focused) {
|
|
|
|
if (frame.fbutton)
|
2002-05-25 00:29:44 +00:00
|
|
|
XSetWindowBackgroundPixmap(blackbox->getXDisplay(),
|
|
|
|
frame.maximize_button, frame.fbutton);
|
2002-04-11 03:20:38 +00:00
|
|
|
else
|
2002-05-25 00:29:44 +00:00
|
|
|
XSetWindowBackground(blackbox->getXDisplay(), frame.maximize_button,
|
2002-05-16 22:35:59 +00:00
|
|
|
frame.fbutton_pixel);
|
2002-04-11 03:20:38 +00:00
|
|
|
} else {
|
|
|
|
if (frame.ubutton)
|
2002-05-25 00:29:44 +00:00
|
|
|
XSetWindowBackgroundPixmap(blackbox->getXDisplay(),
|
|
|
|
frame.maximize_button, frame.ubutton);
|
2002-04-11 03:20:38 +00:00
|
|
|
else
|
2002-05-25 00:29:44 +00:00
|
|
|
XSetWindowBackground(blackbox->getXDisplay(), frame.maximize_button,
|
2002-05-16 22:35:59 +00:00
|
|
|
frame.ubutton_pixel);
|
2002-04-11 03:20:38 +00:00
|
|
|
}
|
|
|
|
} else {
|
|
|
|
if (frame.pbutton)
|
2002-05-25 00:29:44 +00:00
|
|
|
XSetWindowBackgroundPixmap(blackbox->getXDisplay(),
|
|
|
|
frame.maximize_button, frame.pbutton);
|
2002-04-11 03:20:38 +00:00
|
|
|
else
|
2002-05-25 00:29:44 +00:00
|
|
|
XSetWindowBackground(blackbox->getXDisplay(), frame.maximize_button,
|
2002-05-16 22:35:59 +00:00
|
|
|
frame.pbutton_pixel);
|
2002-04-11 03:20:38 +00:00
|
|
|
}
|
2002-05-25 00:29:44 +00:00
|
|
|
XClearWindow(blackbox->getXDisplay(), frame.maximize_button);
|
2002-04-11 03:20:38 +00:00
|
|
|
|
2002-05-25 00:29:44 +00:00
|
|
|
BPen pen((flags.focused) ? screen->getWindowStyle()->b_pic_focus :
|
|
|
|
screen->getWindowStyle()->b_pic_unfocus);
|
|
|
|
XDrawRectangle(blackbox->getXDisplay(), frame.maximize_button, pen.gc(),
|
|
|
|
2, 2, (frame.button_w - 5), (frame.button_w - 5));
|
|
|
|
XDrawLine(blackbox->getXDisplay(), frame.maximize_button, pen.gc(),
|
2002-05-16 22:35:59 +00:00
|
|
|
2, 3, (frame.button_w - 3), 3);
|
2002-04-11 03:20:38 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
|
2002-05-25 00:29:44 +00:00
|
|
|
void BlackboxWindow::redrawCloseButton(bool pressed) {
|
2002-04-11 03:20:38 +00:00
|
|
|
if (! pressed) {
|
|
|
|
if (flags.focused) {
|
|
|
|
if (frame.fbutton)
|
2002-05-25 00:29:44 +00:00
|
|
|
XSetWindowBackgroundPixmap(blackbox->getXDisplay(), frame.close_button,
|
2002-05-16 22:35:59 +00:00
|
|
|
frame.fbutton);
|
2002-04-11 03:20:38 +00:00
|
|
|
else
|
2002-05-25 00:29:44 +00:00
|
|
|
XSetWindowBackground(blackbox->getXDisplay(), frame.close_button,
|
2002-05-16 22:35:59 +00:00
|
|
|
frame.fbutton_pixel);
|
2002-04-11 03:20:38 +00:00
|
|
|
} else {
|
|
|
|
if (frame.ubutton)
|
2002-05-25 00:29:44 +00:00
|
|
|
XSetWindowBackgroundPixmap(blackbox->getXDisplay(), frame.close_button,
|
2002-05-16 22:35:59 +00:00
|
|
|
frame.ubutton);
|
2002-04-11 03:20:38 +00:00
|
|
|
else
|
2002-05-25 00:29:44 +00:00
|
|
|
XSetWindowBackground(blackbox->getXDisplay(), frame.close_button,
|
2002-05-16 22:35:59 +00:00
|
|
|
frame.ubutton_pixel);
|
2002-04-11 03:20:38 +00:00
|
|
|
}
|
|
|
|
} else {
|
|
|
|
if (frame.pbutton)
|
2002-05-25 00:29:44 +00:00
|
|
|
XSetWindowBackgroundPixmap(blackbox->getXDisplay(),
|
|
|
|
frame.close_button, frame.pbutton);
|
2002-04-11 03:20:38 +00:00
|
|
|
else
|
2002-05-25 00:29:44 +00:00
|
|
|
XSetWindowBackground(blackbox->getXDisplay(),
|
|
|
|
frame.close_button, frame.pbutton_pixel);
|
2002-04-11 03:20:38 +00:00
|
|
|
}
|
2002-05-25 00:29:44 +00:00
|
|
|
XClearWindow(blackbox->getXDisplay(), frame.close_button);
|
2002-04-11 03:20:38 +00:00
|
|
|
|
2002-05-25 00:29:44 +00:00
|
|
|
BPen pen((flags.focused) ? screen->getWindowStyle()->b_pic_focus :
|
|
|
|
screen->getWindowStyle()->b_pic_unfocus);
|
|
|
|
XDrawLine(blackbox->getXDisplay(), frame.close_button, pen.gc(),
|
|
|
|
2, 2, (frame.button_w - 3), (frame.button_w - 3));
|
|
|
|
XDrawLine(blackbox->getXDisplay(), frame.close_button, pen.gc(),
|
|
|
|
2, (frame.button_w - 3), (frame.button_w - 3), 2);
|
2002-04-11 03:20:38 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
|
2002-06-29 23:50:04 +00:00
|
|
|
void BlackboxWindow::mapRequestEvent(const XMapRequestEvent *re) {
|
2002-05-25 00:29:44 +00:00
|
|
|
if (re->window != client.window)
|
|
|
|
return;
|
|
|
|
|
2002-04-11 03:20:38 +00:00
|
|
|
#ifdef DEBUG
|
2002-05-25 00:29:44 +00:00
|
|
|
fprintf(stderr, "BlackboxWindow::mapRequestEvent() for 0x%lx\n",
|
|
|
|
client.window);
|
2002-04-11 03:20:38 +00:00
|
|
|
#endif // DEBUG
|
|
|
|
|
2002-05-25 00:29:44 +00:00
|
|
|
switch (current_state) {
|
|
|
|
case IconicState:
|
|
|
|
iconify();
|
|
|
|
break;
|
2002-04-11 03:20:38 +00:00
|
|
|
|
2002-05-25 00:29:44 +00:00
|
|
|
case WithdrawnState:
|
|
|
|
withdraw();
|
|
|
|
break;
|
2002-04-11 03:20:38 +00:00
|
|
|
|
2002-05-25 00:29:44 +00:00
|
|
|
case NormalState:
|
|
|
|
case InactiveState:
|
|
|
|
case ZoomState:
|
|
|
|
default:
|
|
|
|
show();
|
2002-06-29 23:50:04 +00:00
|
|
|
raise();
|
2002-05-25 00:29:44 +00:00
|
|
|
if (! blackbox->isStartup() && (isTransient() || screen->doFocusNew())) {
|
|
|
|
XSync(blackbox->getXDisplay(), False); // make sure the frame is mapped..
|
2002-04-11 03:20:38 +00:00
|
|
|
setInputFocus();
|
2002-05-25 00:29:44 +00:00
|
|
|
}
|
|
|
|
break;
|
2002-04-11 03:20:38 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2002-06-29 23:50:04 +00:00
|
|
|
void BlackboxWindow::unmapNotifyEvent(const XUnmapEvent *ue) {
|
2002-05-25 00:29:44 +00:00
|
|
|
if (ue->window != client.window)
|
|
|
|
return;
|
|
|
|
|
2002-04-11 03:20:38 +00:00
|
|
|
#ifdef DEBUG
|
2002-05-25 00:29:44 +00:00
|
|
|
fprintf(stderr, "BlackboxWindow::unmapNotifyEvent() for 0x%lx\n",
|
|
|
|
client.window);
|
2002-04-11 03:20:38 +00:00
|
|
|
#endif // DEBUG
|
|
|
|
|
2002-05-25 00:29:44 +00:00
|
|
|
screen->unmanageWindow(this, False);
|
|
|
|
}
|
2002-04-11 03:20:38 +00:00
|
|
|
|
|
|
|
|
2002-06-29 23:50:04 +00:00
|
|
|
void BlackboxWindow::destroyNotifyEvent(const XDestroyWindowEvent *de) {
|
2002-05-25 00:29:44 +00:00
|
|
|
if (de->window != client.window)
|
|
|
|
return;
|
2002-04-11 03:20:38 +00:00
|
|
|
|
|
|
|
#ifdef DEBUG
|
2002-05-25 00:29:44 +00:00
|
|
|
fprintf(stderr, "BlackboxWindow::destroyNotifyEvent() for 0x%lx\n",
|
|
|
|
client.window);
|
2002-04-11 03:20:38 +00:00
|
|
|
#endif // DEBUG
|
|
|
|
|
2002-05-25 00:29:44 +00:00
|
|
|
screen->unmanageWindow(this, False);
|
2002-04-11 03:20:38 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
|
2002-06-29 23:50:04 +00:00
|
|
|
void BlackboxWindow::reparentNotifyEvent(const XReparentEvent *re) {
|
2002-05-25 00:29:44 +00:00
|
|
|
if (re->window != client.window || re->parent == frame.plate)
|
|
|
|
return;
|
|
|
|
|
|
|
|
#ifdef DEBUG
|
|
|
|
fprintf(stderr, "BlackboxWindow::reparentNotifyEvent(): reparent 0x%lx to "
|
|
|
|
"0x%lx.\n", client.window, re->parent);
|
|
|
|
#endif // DEBUG
|
2002-04-11 03:20:38 +00:00
|
|
|
|
2002-05-25 00:29:44 +00:00
|
|
|
XEvent ev;
|
|
|
|
ev.xreparent = *re;
|
|
|
|
XPutBackEvent(blackbox->getXDisplay(), &ev);
|
|
|
|
screen->unmanageWindow(this, True);
|
2002-04-11 03:20:38 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
|
2002-05-25 00:29:44 +00:00
|
|
|
void BlackboxWindow::propertyNotifyEvent(Atom atom) {
|
2002-04-11 03:20:38 +00:00
|
|
|
switch(atom) {
|
|
|
|
case XA_WM_CLASS:
|
|
|
|
case XA_WM_CLIENT_MACHINE:
|
|
|
|
case XA_WM_COMMAND:
|
|
|
|
break;
|
|
|
|
|
2002-05-25 00:29:44 +00:00
|
|
|
case XA_WM_TRANSIENT_FOR: {
|
2002-04-11 03:20:38 +00:00
|
|
|
// determine if this is a transient window
|
2002-05-25 00:29:44 +00:00
|
|
|
getTransientInfo();
|
2002-04-11 03:20:38 +00:00
|
|
|
|
|
|
|
// adjust the window decorations based on transience
|
2002-05-25 00:29:44 +00:00
|
|
|
if (isTransient()) {
|
|
|
|
decorations &= ~(Decor_Maximize | Decor_Handle);
|
|
|
|
functions &= ~Func_Maximize;
|
2002-06-21 20:40:14 +00:00
|
|
|
setAllowedActions();
|
2002-05-25 00:29:44 +00:00
|
|
|
}
|
2002-04-11 03:20:38 +00:00
|
|
|
|
|
|
|
reconfigure();
|
2002-05-25 00:29:44 +00:00
|
|
|
}
|
2002-04-11 03:20:38 +00:00
|
|
|
break;
|
|
|
|
|
|
|
|
case XA_WM_HINTS:
|
|
|
|
getWMHints();
|
|
|
|
break;
|
|
|
|
|
|
|
|
case XA_WM_ICON_NAME:
|
|
|
|
getWMIconName();
|
2002-05-25 00:29:44 +00:00
|
|
|
if (flags.iconic) screen->propagateWindowName(this);
|
2002-04-11 03:20:38 +00:00
|
|
|
break;
|
|
|
|
|
2002-06-21 20:40:14 +00:00
|
|
|
case XAtom::net_wm_name:
|
2002-04-11 03:20:38 +00:00
|
|
|
case XA_WM_NAME:
|
|
|
|
getWMName();
|
|
|
|
|
2002-05-25 00:29:44 +00:00
|
|
|
if (decorations & Decor_Titlebar)
|
2002-04-11 03:20:38 +00:00
|
|
|
redrawLabel();
|
|
|
|
|
2002-05-25 00:29:44 +00:00
|
|
|
screen->propagateWindowName(this);
|
2002-04-11 03:20:38 +00:00
|
|
|
break;
|
|
|
|
|
|
|
|
case XA_WM_NORMAL_HINTS: {
|
|
|
|
getWMNormalHints();
|
|
|
|
|
|
|
|
if ((client.normal_hint_flags & PMinSize) &&
|
|
|
|
(client.normal_hint_flags & PMaxSize)) {
|
|
|
|
if (client.max_width <= client.min_width &&
|
2002-05-25 00:29:44 +00:00
|
|
|
client.max_height <= client.min_height) {
|
|
|
|
decorations &= ~(Decor_Maximize | Decor_Handle);
|
|
|
|
functions &= ~(Func_Resize | Func_Maximize);
|
|
|
|
} else {
|
|
|
|
decorations |= Decor_Maximize | Decor_Handle;
|
|
|
|
functions |= Func_Resize | Func_Maximize;
|
|
|
|
}
|
2002-06-21 20:40:14 +00:00
|
|
|
setAllowedActions();
|
2002-04-11 03:20:38 +00:00
|
|
|
}
|
|
|
|
|
2002-05-25 00:29:44 +00:00
|
|
|
Rect old_rect = frame.rect;
|
2002-04-11 03:20:38 +00:00
|
|
|
|
|
|
|
upsize();
|
|
|
|
|
2002-05-25 00:29:44 +00:00
|
|
|
if (old_rect != frame.rect)
|
2002-04-11 03:20:38 +00:00
|
|
|
reconfigure();
|
|
|
|
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
|
|
|
|
default:
|
2002-06-21 20:40:14 +00:00
|
|
|
if (atom == xatom->getAtom(XAtom::wm_protocols)) {
|
2002-04-11 03:20:38 +00:00
|
|
|
getWMProtocols();
|
|
|
|
|
2002-05-25 00:29:44 +00:00
|
|
|
if ((decorations & Decor_Close) && (! frame.close_button)) {
|
2002-04-11 03:20:38 +00:00
|
|
|
createCloseButton();
|
2002-05-25 00:29:44 +00:00
|
|
|
if (decorations & Decor_Titlebar) {
|
|
|
|
positionButtons(True);
|
|
|
|
XMapSubwindows(blackbox->getXDisplay(), frame.title);
|
2002-05-14 19:28:34 +00:00
|
|
|
}
|
2002-04-11 03:20:38 +00:00
|
|
|
if (windowmenu) windowmenu->reconfigure();
|
|
|
|
}
|
2002-06-21 20:40:14 +00:00
|
|
|
} else if (atom == xatom->getAtom(XAtom::net_wm_strut)) {
|
|
|
|
updateStrut();
|
2002-04-11 03:20:38 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2002-06-29 23:50:04 +00:00
|
|
|
void BlackboxWindow::exposeEvent(const XExposeEvent *ee) {
|
2002-05-25 00:29:44 +00:00
|
|
|
if (frame.label == ee->window && (decorations & Decor_Titlebar))
|
2002-04-11 03:20:38 +00:00
|
|
|
redrawLabel();
|
|
|
|
else if (frame.close_button == ee->window)
|
|
|
|
redrawCloseButton(False);
|
|
|
|
else if (frame.maximize_button == ee->window)
|
|
|
|
redrawMaximizeButton(flags.maximized);
|
|
|
|
else if (frame.iconify_button == ee->window)
|
|
|
|
redrawIconifyButton(False);
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2002-06-29 23:50:04 +00:00
|
|
|
void BlackboxWindow::configureRequestEvent(const XConfigureRequestEvent *cr) {
|
2002-05-25 00:29:44 +00:00
|
|
|
if (cr->window != client.window || flags.iconic)
|
|
|
|
return;
|
2002-04-11 03:20:38 +00:00
|
|
|
|
2002-05-25 00:29:44 +00:00
|
|
|
int cx = frame.rect.x(), cy = frame.rect.y();
|
|
|
|
unsigned int cw = frame.rect.width(), ch = frame.rect.height();
|
2002-04-11 03:20:38 +00:00
|
|
|
|
2002-05-25 00:29:44 +00:00
|
|
|
if (cr->value_mask & CWBorderWidth)
|
|
|
|
client.old_bw = cr->border_width;
|
2002-04-11 03:20:38 +00:00
|
|
|
|
2002-05-25 00:29:44 +00:00
|
|
|
if (cr->value_mask & CWX)
|
|
|
|
cx = cr->x - frame.margin.left;
|
2002-04-11 03:20:38 +00:00
|
|
|
|
2002-05-25 00:29:44 +00:00
|
|
|
if (cr->value_mask & CWY)
|
|
|
|
cy = cr->y - frame.margin.top;
|
2002-04-11 03:20:38 +00:00
|
|
|
|
2002-05-25 00:29:44 +00:00
|
|
|
if (cr->value_mask & CWWidth)
|
|
|
|
cw = cr->width + frame.margin.left + frame.margin.right;
|
2002-04-11 03:20:38 +00:00
|
|
|
|
2002-05-25 00:29:44 +00:00
|
|
|
if (cr->value_mask & CWHeight)
|
|
|
|
ch = cr->height + frame.margin.top + frame.margin.bottom;
|
2002-04-11 03:20:38 +00:00
|
|
|
|
2002-05-25 00:29:44 +00:00
|
|
|
if (frame.rect != Rect(cx, cy, cw, ch))
|
|
|
|
configure(cx, cy, cw, ch);
|
2002-04-11 03:20:38 +00:00
|
|
|
|
2002-05-25 00:29:44 +00:00
|
|
|
if (cr->value_mask & CWStackMode) {
|
|
|
|
switch (cr->detail) {
|
|
|
|
case Below:
|
|
|
|
case BottomIf:
|
2002-06-29 23:50:04 +00:00
|
|
|
lower();
|
2002-05-25 00:29:44 +00:00
|
|
|
break;
|
2002-04-11 03:20:38 +00:00
|
|
|
|
2002-05-25 00:29:44 +00:00
|
|
|
case Above:
|
|
|
|
case TopIf:
|
|
|
|
default:
|
2002-06-29 23:50:04 +00:00
|
|
|
raise();
|
2002-05-25 00:29:44 +00:00
|
|
|
break;
|
2002-04-11 03:20:38 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2002-06-29 23:50:04 +00:00
|
|
|
void BlackboxWindow::grabButtons(void) {
|
|
|
|
const BInput::MouseBindingList &mbindings = input->getMouseBindings();
|
|
|
|
|
|
|
|
BInput::MouseBindingList::const_iterator mit = mbindings.begin();
|
|
|
|
const BInput::MouseBindingList::const_iterator mend = mbindings.end();
|
|
|
|
for (; mit != mend; ++mit) {
|
|
|
|
// dont grab for an action the window can't perform
|
|
|
|
//if (! (mit->action == BInput::BeginMove && functions & Func_Move) &&
|
|
|
|
// ! (mit->action == BInput::BeginResize && functions & Func_Resize)) {
|
|
|
|
switch (mit->event) {
|
|
|
|
case BInput::WindowClientPress:
|
|
|
|
blackbox->grabButton(mit->button, mit->state, frame.plate, True,
|
|
|
|
ButtonPressMask, GrabModeSync, GrabModeSync,
|
|
|
|
frame.plate, None);
|
|
|
|
break;
|
|
|
|
case BInput::WindowDrag:
|
|
|
|
blackbox->grabButton(mit->button, mit->state, frame.window, True,
|
|
|
|
ButtonMotionMask, GrabModeAsync, GrabModeAsync,
|
|
|
|
frame.window, None);
|
|
|
|
default:
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
2002-04-11 03:20:38 +00:00
|
|
|
|
2002-05-25 00:29:44 +00:00
|
|
|
|
2002-06-29 23:50:04 +00:00
|
|
|
void BlackboxWindow::ungrabButtons(void) {
|
|
|
|
const BInput::MouseBindingList &mbindings = input->getMouseBindings();
|
|
|
|
|
|
|
|
BInput::MouseBindingList::const_iterator mit = mbindings.begin();
|
|
|
|
const BInput::MouseBindingList::const_iterator mend = mbindings.end();
|
|
|
|
for (; mit != mend; ++mit) {
|
|
|
|
switch (mit->event) {
|
|
|
|
case BInput::WindowClientPress:
|
|
|
|
blackbox->ungrabButton(mit->button, mit->state, frame.plate);
|
|
|
|
break;
|
|
|
|
case BInput::WindowDrag:
|
|
|
|
blackbox->ungrabButton(mit->button, mit->state, frame.window);
|
|
|
|
default:
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2002-05-25 00:29:44 +00:00
|
|
|
|
2002-06-29 23:50:04 +00:00
|
|
|
void BlackboxWindow::buttonPressEvent(const XButtonEvent *be) {
|
|
|
|
if (windowmenu && windowmenu->isVisible()) windowmenu->hide();
|
|
|
|
|
|
|
|
if (frame.maximize_button == be->window) {
|
|
|
|
if (input->hasAction(be->button, be->state, BInput::MaximizeButtonClick))
|
|
|
|
redrawMaximizeButton(True);
|
|
|
|
} else if (frame.iconify_button == be->window) {
|
|
|
|
if (input->hasAction(be->button, be->state, BInput::IconifyButtonClick))
|
|
|
|
redrawIconifyButton(True);
|
|
|
|
} else if (frame.close_button == be->window) {
|
|
|
|
if (input->hasAction(be->button, be->state, BInput::CloseButtonClick))
|
|
|
|
redrawCloseButton(True);
|
|
|
|
} else if (frame.title == be->window || frame.label == be->window) {
|
|
|
|
if (be->time - lastButtonPressTime <= blackbox->getDoubleClickInterval()) {
|
|
|
|
lastButtonPressTime = 0;
|
|
|
|
input->doAction(this, be->button, be->state,
|
|
|
|
BInput::WindowTitleDoublePress);
|
2002-05-25 00:29:44 +00:00
|
|
|
} else {
|
2002-06-29 23:50:04 +00:00
|
|
|
lastButtonPressTime = be->time;
|
|
|
|
input->doAction(this, be->button, be->state,
|
|
|
|
BInput::WindowTitlePress);
|
|
|
|
}
|
|
|
|
} else if (frame.plate == be->window) {
|
|
|
|
input->doAction(this, be->button, be->state, BInput::WindowClientPress);
|
|
|
|
// buttons on the client window are grabbed in Sync mode, so we need to let
|
|
|
|
// events back through again
|
|
|
|
XAllowEvents(blackbox->getXDisplay(), ReplayPointer, be->time);
|
|
|
|
} else if (frame.window == be->window || frame.handle == be->window) {
|
|
|
|
input->doAction(this, be->button, be->state, BInput::WindowFramePress);
|
|
|
|
}
|
|
|
|
}
|
2002-04-11 03:20:38 +00:00
|
|
|
|
|
|
|
|
2002-06-29 23:50:04 +00:00
|
|
|
void BlackboxWindow::showWindowMenu(int root_x, int root_y) {
|
|
|
|
if (! windowmenu || windowmenu->isVisible())
|
|
|
|
return;
|
|
|
|
|
|
|
|
root_x -= windowmenu->getWidth() / 2;
|
|
|
|
root_y -= windowmenu->getHeight() / 2;
|
2002-05-25 00:29:44 +00:00
|
|
|
|
2002-06-29 23:50:04 +00:00
|
|
|
// snap the window menu into a corner/side if necessary
|
|
|
|
int left_edge, right_edge, top_edge, bottom_edge;
|
|
|
|
|
|
|
|
left_edge = frame.rect.x();
|
|
|
|
right_edge = frame.rect.right() - windowmenu->getWidth() - frame.border_w - 1;
|
|
|
|
if (decorations & Decor_Titlebar)
|
|
|
|
top_edge = frame.rect.y() + frame.title_h + frame.border_w;
|
|
|
|
else
|
|
|
|
top_edge = frame.rect.y() + frame.border_w;
|
|
|
|
if (decorations & Decor_Handle)
|
|
|
|
bottom_edge = frame.rect.bottom() - frame.handle_h - (frame.border_w * 3) -
|
|
|
|
windowmenu->getHeight();
|
|
|
|
else
|
|
|
|
bottom_edge = frame.rect.bottom() - windowmenu->getHeight() -
|
|
|
|
frame.border_w + 1;
|
|
|
|
|
|
|
|
if (root_x > right_edge)
|
|
|
|
root_x = right_edge;
|
|
|
|
if (root_x < left_edge)
|
|
|
|
root_x = left_edge;
|
|
|
|
|
|
|
|
if (root_y > bottom_edge)
|
|
|
|
root_y = bottom_edge;
|
|
|
|
if (root_y < top_edge)
|
|
|
|
root_y = top_edge;
|
|
|
|
|
|
|
|
|
|
|
|
windowmenu->move(root_x, root_y);
|
|
|
|
windowmenu->show();
|
|
|
|
XRaiseWindow(blackbox->getXDisplay(), windowmenu->getWindowID());
|
|
|
|
XRaiseWindow(blackbox->getXDisplay(),
|
|
|
|
windowmenu->getSendToMenu()->getWindowID());
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
void BlackboxWindow::buttonReleaseEvent(const XButtonEvent *re) {
|
|
|
|
// get the proper state, without the button that was released
|
|
|
|
unsigned int state;
|
|
|
|
switch (re->button) {
|
|
|
|
case Button1:
|
|
|
|
state = re->state & ~Button1Mask;
|
|
|
|
break;
|
|
|
|
case Button2:
|
|
|
|
state = re->state & ~Button2Mask;
|
|
|
|
break;
|
|
|
|
case Button3:
|
|
|
|
state = re->state & ~Button3Mask;
|
|
|
|
break;
|
|
|
|
case Button4:
|
|
|
|
state = re->state & ~Button4Mask;
|
|
|
|
break;
|
|
|
|
case Button5:
|
|
|
|
state = re->state & ~Button5Mask;
|
|
|
|
break;
|
|
|
|
default:
|
|
|
|
assert(false); // unhandled button
|
|
|
|
}
|
2002-05-25 00:29:44 +00:00
|
|
|
|
2002-06-29 23:50:04 +00:00
|
|
|
if (frame.maximize_button == re->window) {
|
|
|
|
if ((re->x < 0 || re->x >= static_cast<signed>(frame.button_w)) ||
|
|
|
|
(re->y < 0 || re->y >= static_cast<signed>(frame.button_w)) ||
|
|
|
|
! input->doAction(this, re->button, state,
|
|
|
|
BInput::MaximizeButtonClick))
|
2002-05-25 00:29:44 +00:00
|
|
|
redrawMaximizeButton(flags.maximized);
|
2002-06-29 23:50:04 +00:00
|
|
|
} else if (frame.iconify_button == re->window) {
|
|
|
|
if ((re->x < 0 || re->x >= static_cast<signed>(frame.button_w)) ||
|
|
|
|
(re->y < 0 || re->y >= static_cast<signed>(frame.button_w)) ||
|
|
|
|
! input->doAction(this, re->button, state,
|
|
|
|
BInput::IconifyButtonClick))
|
2002-05-25 00:29:44 +00:00
|
|
|
redrawIconifyButton(False);
|
2002-06-29 23:50:04 +00:00
|
|
|
} else if (frame.close_button == re->window) {
|
2002-06-30 03:30:54 +00:00
|
|
|
if (! ((re->x < 0 || re->x >= static_cast<signed>(frame.button_w)) ||
|
|
|
|
(re->y < 0 || re->y >= static_cast<signed>(frame.button_w))))
|
2002-06-29 23:50:04 +00:00
|
|
|
input->doAction(this, re->button, state, BInput::CloseButtonClick);
|
|
|
|
redrawCloseButton(False);
|
2002-05-25 00:29:44 +00:00
|
|
|
} else if (flags.moving) {
|
2002-06-21 20:40:14 +00:00
|
|
|
endMove();
|
2002-05-25 00:29:44 +00:00
|
|
|
} else if (flags.resizing) {
|
2002-06-21 20:40:14 +00:00
|
|
|
endResize();
|
2002-06-29 23:50:04 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
void BlackboxWindow::motionNotifyEvent(const XMotionEvent *me) {
|
|
|
|
// get the button that is being used
|
|
|
|
// get the proper state, without the button that is being used
|
|
|
|
unsigned int button;
|
|
|
|
unsigned int state;
|
|
|
|
if (me->state & Button1Mask) {
|
|
|
|
button = Button1;
|
|
|
|
state = me->state & ~Button1Mask;
|
|
|
|
} else if (me->state & Button2Mask) {
|
|
|
|
button = Button2;
|
|
|
|
state = me->state & ~Button2Mask;
|
|
|
|
} else if (me->state & Button3Mask) {
|
|
|
|
button = Button3;
|
|
|
|
state = me->state & ~Button3Mask;
|
|
|
|
} else if (me->state & Button4Mask) {
|
|
|
|
button = Button4;
|
|
|
|
state = me->state & ~Button4Mask;
|
|
|
|
} else if (me->state & Button5Mask) {
|
|
|
|
button = Button5;
|
|
|
|
state = me->state & ~Button5Mask;
|
|
|
|
} else {
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (flags.moving) {
|
|
|
|
doMove(me->x_root, me->y_root);
|
|
|
|
} else if (flags.resizing) {
|
|
|
|
doResize(me->x_root, me->y_root);
|
|
|
|
} else {
|
|
|
|
if (frame.title == me->window || frame.label == me->window)
|
|
|
|
input->doAction(this, button, state, BInput::WindowTitleDrag);
|
|
|
|
else if (frame.handle == me->window)
|
|
|
|
input->doAction(this, button, state, BInput::WindowHandleDrag);
|
|
|
|
else if (frame.left_grip == me->window)
|
|
|
|
input->doAction(this, button, state, BInput::WindowLeftGripDrag);
|
|
|
|
else if (frame.right_grip == me->window)
|
|
|
|
input->doAction(this, button, state, BInput::WindowRightGripDrag);
|
|
|
|
else if (frame.window == me->window)
|
|
|
|
input->doAction(this, button, state, BInput::WindowDrag);
|
2002-06-21 20:40:14 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
void BlackboxWindow::beginMove(int x_root, int y_root) {
|
|
|
|
assert(! (flags.resizing || flags.moving));
|
|
|
|
|
|
|
|
/*
|
|
|
|
Only one window can be moved/resized at a time. If another window is already
|
|
|
|
being moved or resized, then stop it before whating to work with this one.
|
|
|
|
*/
|
|
|
|
BlackboxWindow *changing = blackbox->getChangingWindow();
|
|
|
|
if (changing && changing != this) {
|
|
|
|
if (changing->flags.moving)
|
|
|
|
changing->endMove();
|
|
|
|
else // if (changing->flags.resizing)
|
|
|
|
changing->endResize();
|
|
|
|
}
|
|
|
|
|
|
|
|
XGrabPointer(blackbox->getXDisplay(), frame.window, False,
|
|
|
|
PointerMotionMask | ButtonReleaseMask,
|
|
|
|
GrabModeAsync, GrabModeAsync,
|
|
|
|
None, blackbox->getMoveCursor(), CurrentTime);
|
|
|
|
|
|
|
|
if (windowmenu && windowmenu->isVisible())
|
|
|
|
windowmenu->hide();
|
|
|
|
|
|
|
|
flags.moving = True;
|
|
|
|
blackbox->setChangingWindow(this);
|
|
|
|
|
|
|
|
if (! screen->doOpaqueMove()) {
|
|
|
|
XGrabServer(blackbox->getXDisplay());
|
|
|
|
|
|
|
|
frame.changing = frame.rect;
|
|
|
|
screen->showPosition(frame.changing.x(), frame.changing.y());
|
|
|
|
|
|
|
|
XDrawRectangle(blackbox->getXDisplay(), screen->getRootWindow(),
|
|
|
|
screen->getOpGC(),
|
|
|
|
frame.changing.x(),
|
|
|
|
frame.changing.y(),
|
|
|
|
frame.changing.width() - 1,
|
|
|
|
frame.changing.height() - 1);
|
|
|
|
}
|
|
|
|
|
|
|
|
frame.grab_x = x_root - frame.rect.x() - frame.border_w;
|
|
|
|
frame.grab_y = y_root - frame.rect.y() - frame.border_w;
|
|
|
|
}
|
|
|
|
|
2002-06-22 04:48:33 +00:00
|
|
|
|
2002-06-21 20:40:14 +00:00
|
|
|
void BlackboxWindow::doMove(int x_root, int y_root) {
|
|
|
|
assert(flags.moving);
|
|
|
|
assert(blackbox->getChangingWindow() == this);
|
|
|
|
|
|
|
|
int dx = x_root - frame.grab_x, dy = y_root - frame.grab_y;
|
|
|
|
dx -= frame.border_w;
|
|
|
|
dy -= frame.border_w;
|
|
|
|
|
|
|
|
const int snap_distance = screen->getEdgeSnapThreshold();
|
|
|
|
|
|
|
|
if (snap_distance) {
|
|
|
|
// window corners
|
|
|
|
const int wleft = dx,
|
2002-06-22 04:48:33 +00:00
|
|
|
wright = dx + frame.rect.width() - 1,
|
|
|
|
wtop = dy,
|
|
|
|
wbottom = dy + frame.rect.height() - 1;
|
|
|
|
|
|
|
|
if (screen->getWindowToWindowSnap()) {
|
|
|
|
Workspace *w = screen->getWorkspace(getWorkspaceNumber());
|
|
|
|
assert(w);
|
|
|
|
|
|
|
|
// try snap to another window
|
|
|
|
for (unsigned int i = 0, c = w->getCount(); i < c; ++i) {
|
|
|
|
BlackboxWindow *snapwin = w->getWindow(i);
|
|
|
|
if (snapwin == this)
|
|
|
|
continue; // don't snap to self
|
|
|
|
|
|
|
|
bool snapped = False;
|
|
|
|
|
|
|
|
const Rect &winrect = snapwin->frameRect();
|
|
|
|
int dleft = std::abs(wright - winrect.left()),
|
|
|
|
dright = std::abs(wleft - winrect.right()),
|
|
|
|
dtop = std::abs(wbottom - winrect.top()),
|
|
|
|
dbottom = std::abs(wtop - winrect.bottom());
|
|
|
|
|
|
|
|
if (wtop >= (signed)(winrect.y() - frame.rect.height() + 1) &&
|
|
|
|
wtop < (signed)(winrect.y() + winrect.height() - 1)) {
|
|
|
|
|
|
|
|
// snap left of other window?
|
|
|
|
if (dleft < snap_distance && dleft <= dright) {
|
|
|
|
dx = winrect.left() - frame.rect.width();
|
|
|
|
snapped = True;
|
|
|
|
}
|
|
|
|
// snap right of other window?
|
|
|
|
else if (dright < snap_distance) {
|
|
|
|
dx = winrect.right() + 1;
|
|
|
|
snapped = True;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (snapped) {
|
|
|
|
if (screen->getWindowCornerSnap()) {
|
|
|
|
// try corner-snap to its other sides
|
|
|
|
dtop = std::abs(wtop - winrect.top());
|
|
|
|
dbottom = std::abs(wbottom - winrect.bottom());
|
|
|
|
if (dtop < snap_distance && dtop <= dbottom)
|
|
|
|
dy = winrect.top();
|
|
|
|
else if (dbottom < snap_distance)
|
|
|
|
dy = winrect.bottom() - frame.rect.height() + 1;
|
|
|
|
}
|
|
|
|
|
|
|
|
continue;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
if (wleft >= (signed)(winrect.x() - frame.rect.width() + 1) &&
|
|
|
|
wleft < (signed)(winrect.x() + winrect.width() - 1)) {
|
|
|
|
|
|
|
|
// snap top of other window?
|
|
|
|
if (dtop < snap_distance && dtop <= dbottom) {
|
|
|
|
dy = winrect.top() - frame.rect.height();
|
|
|
|
snapped = True;
|
|
|
|
}
|
|
|
|
// snap bottom of other window?
|
|
|
|
else if (dbottom < snap_distance) {
|
|
|
|
dy = winrect.bottom() + 1;
|
|
|
|
snapped = True;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (snapped) {
|
|
|
|
if (screen->getWindowCornerSnap()) {
|
|
|
|
// try corner-snap to its other sides
|
|
|
|
dleft = std::abs(wleft - winrect.left());
|
|
|
|
dright = std::abs(wright - winrect.right());
|
|
|
|
if (dleft < snap_distance && dleft <= dright)
|
|
|
|
dx = winrect.left();
|
|
|
|
else if (dright < snap_distance)
|
|
|
|
dx = winrect.right() - frame.rect.width() + 1;
|
|
|
|
}
|
|
|
|
|
|
|
|
continue;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
// try snap to the screen's available area
|
|
|
|
Rect srect = screen->availableArea();
|
2002-06-21 20:40:14 +00:00
|
|
|
|
|
|
|
int dleft = std::abs(wleft - srect.left()),
|
2002-06-22 04:48:33 +00:00
|
|
|
dright = std::abs(wright - srect.right()),
|
|
|
|
dtop = std::abs(wtop - srect.top()),
|
2002-06-21 20:40:14 +00:00
|
|
|
dbottom = std::abs(wbottom - srect.bottom());
|
|
|
|
|
|
|
|
// snap left?
|
2002-06-27 17:54:32 +00:00
|
|
|
if (dleft < snap_distance && dleft <= dright)
|
2002-06-21 20:40:14 +00:00
|
|
|
dx = srect.left();
|
|
|
|
// snap right?
|
2002-06-27 17:54:32 +00:00
|
|
|
else if (dright < snap_distance)
|
2002-06-21 20:40:14 +00:00
|
|
|
dx = srect.right() - frame.rect.width() + 1;
|
|
|
|
|
|
|
|
// snap top?
|
2002-06-27 17:54:32 +00:00
|
|
|
if (dtop < snap_distance && dtop <= dbottom)
|
2002-06-21 20:40:14 +00:00
|
|
|
dy = srect.top();
|
|
|
|
// snap bottom?
|
2002-06-27 17:54:32 +00:00
|
|
|
else if (dbottom < snap_distance)
|
2002-06-21 20:40:14 +00:00
|
|
|
dy = srect.bottom() - frame.rect.height() + 1;
|
|
|
|
|
|
|
|
srect = screen->getRect(); // now get the full screen
|
|
|
|
|
|
|
|
dleft = std::abs(wleft - srect.left()),
|
|
|
|
dright = std::abs(wright - srect.right()),
|
|
|
|
dtop = std::abs(wtop - srect.top()),
|
|
|
|
dbottom = std::abs(wbottom - srect.bottom());
|
|
|
|
|
|
|
|
// snap left?
|
2002-06-27 17:54:32 +00:00
|
|
|
if (dleft < snap_distance && dleft <= dright)
|
2002-06-21 20:40:14 +00:00
|
|
|
dx = srect.left();
|
|
|
|
// snap right?
|
2002-06-27 17:54:32 +00:00
|
|
|
else if (dright < snap_distance)
|
2002-06-21 20:40:14 +00:00
|
|
|
dx = srect.right() - frame.rect.width() + 1;
|
|
|
|
|
|
|
|
// snap top?
|
2002-06-27 17:54:32 +00:00
|
|
|
if (dtop < snap_distance && dtop <= dbottom)
|
2002-06-21 20:40:14 +00:00
|
|
|
dy = srect.top();
|
|
|
|
// snap bottom?
|
2002-06-27 17:54:32 +00:00
|
|
|
else if (dbottom < snap_distance)
|
2002-06-21 20:40:14 +00:00
|
|
|
dy = srect.bottom() - frame.rect.height() + 1;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (screen->doOpaqueMove()) {
|
|
|
|
configure(dx, dy, frame.rect.width(), frame.rect.height());
|
|
|
|
} else {
|
|
|
|
XDrawRectangle(blackbox->getXDisplay(), screen->getRootWindow(),
|
|
|
|
screen->getOpGC(),
|
|
|
|
frame.changing.x(),
|
|
|
|
frame.changing.y(),
|
|
|
|
frame.changing.width() - 1,
|
|
|
|
frame.changing.height() - 1);
|
|
|
|
|
|
|
|
frame.changing.setPos(dx, dy);
|
|
|
|
|
|
|
|
XDrawRectangle(blackbox->getXDisplay(), screen->getRootWindow(),
|
|
|
|
screen->getOpGC(),
|
|
|
|
frame.changing.x(),
|
|
|
|
frame.changing.y(),
|
|
|
|
frame.changing.width() - 1,
|
|
|
|
frame.changing.height() - 1);
|
|
|
|
}
|
|
|
|
|
|
|
|
screen->showPosition(dx, dy);
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
void BlackboxWindow::endMove(void) {
|
|
|
|
assert(flags.moving);
|
|
|
|
assert(blackbox->getChangingWindow() == this);
|
|
|
|
|
|
|
|
flags.moving = False;
|
|
|
|
blackbox->setChangingWindow(0);
|
|
|
|
|
|
|
|
if (! screen->doOpaqueMove()) {
|
|
|
|
/* when drawing the rubber band, we need to make sure we only draw inside
|
|
|
|
* the frame... frame.changing_* contain the new coords for the window,
|
|
|
|
* so we need to subtract 1 from changing_w/changing_h every where we
|
|
|
|
* draw the rubber band (for both moving and resizing)
|
|
|
|
*/
|
2002-05-25 00:29:44 +00:00
|
|
|
XDrawRectangle(blackbox->getXDisplay(), screen->getRootWindow(),
|
|
|
|
screen->getOpGC(), frame.changing.x(), frame.changing.y(),
|
|
|
|
frame.changing.width() - 1, frame.changing.height() - 1);
|
2002-06-21 20:40:14 +00:00
|
|
|
XUngrabServer(blackbox->getXDisplay());
|
|
|
|
|
|
|
|
configure(frame.changing.x(), frame.changing.y(),
|
|
|
|
frame.changing.width(), frame.changing.height());
|
|
|
|
} else {
|
|
|
|
configure(frame.rect.x(), frame.rect.y(),
|
|
|
|
frame.rect.width(), frame.rect.height());
|
|
|
|
}
|
|
|
|
screen->hideGeometry();
|
2002-04-11 03:20:38 +00:00
|
|
|
|
2002-06-21 20:40:14 +00:00
|
|
|
XUngrabPointer(blackbox->getXDisplay(), CurrentTime);
|
2002-04-11 03:20:38 +00:00
|
|
|
|
2002-06-21 20:40:14 +00:00
|
|
|
// if there are any left over motions from the move, drop them now
|
|
|
|
XSync(blackbox->getXDisplay(), false); // make sure we don't miss any
|
|
|
|
XEvent e;
|
|
|
|
while (XCheckTypedWindowEvent(blackbox->getXDisplay(), frame.window,
|
|
|
|
MotionNotify, &e));
|
|
|
|
}
|
2002-04-11 03:20:38 +00:00
|
|
|
|
|
|
|
|
2002-06-21 20:40:14 +00:00
|
|
|
void BlackboxWindow::beginResize(int x_root, int y_root, Corner dir) {
|
|
|
|
assert(! (flags.resizing || flags.moving));
|
|
|
|
|
|
|
|
/*
|
|
|
|
Only one window can be moved/resized at a time. If another window is already
|
|
|
|
being moved or resized, then stop it before whating to work with this one.
|
|
|
|
*/
|
|
|
|
BlackboxWindow *changing = blackbox->getChangingWindow();
|
|
|
|
if (changing && changing != this) {
|
|
|
|
if (changing->flags.moving)
|
|
|
|
changing->endMove();
|
|
|
|
else // if (changing->flags.resizing)
|
|
|
|
changing->endResize();
|
2002-04-28 11:26:55 +00:00
|
|
|
}
|
2002-06-21 20:40:14 +00:00
|
|
|
|
|
|
|
resize_dir = dir;
|
|
|
|
|
|
|
|
Cursor cursor;
|
|
|
|
Corner anchor;
|
|
|
|
|
|
|
|
switch (resize_dir) {
|
|
|
|
case BottomLeft:
|
|
|
|
anchor = TopRight;
|
|
|
|
cursor = blackbox->getLowerLeftAngleCursor();
|
|
|
|
break;
|
|
|
|
|
|
|
|
case BottomRight:
|
|
|
|
anchor = TopLeft;
|
|
|
|
cursor = blackbox->getLowerRightAngleCursor();
|
|
|
|
break;
|
|
|
|
|
|
|
|
case TopLeft:
|
|
|
|
anchor = BottomRight;
|
|
|
|
cursor = blackbox->getUpperLeftAngleCursor();
|
|
|
|
break;
|
|
|
|
|
|
|
|
case TopRight:
|
|
|
|
anchor = BottomLeft;
|
|
|
|
cursor = blackbox->getUpperRightAngleCursor();
|
|
|
|
break;
|
|
|
|
|
|
|
|
default:
|
|
|
|
assert(false); // unhandled Corner
|
|
|
|
}
|
|
|
|
|
|
|
|
XGrabServer(blackbox->getXDisplay());
|
|
|
|
XGrabPointer(blackbox->getXDisplay(), frame.window, False,
|
|
|
|
PointerMotionMask | ButtonReleaseMask,
|
|
|
|
GrabModeAsync, GrabModeAsync, None, cursor, CurrentTime);
|
|
|
|
|
|
|
|
flags.resizing = True;
|
|
|
|
blackbox->setChangingWindow(this);
|
|
|
|
|
|
|
|
int gw, gh;
|
|
|
|
frame.changing = frame.rect;
|
|
|
|
|
|
|
|
constrain(anchor, &gw, &gh);
|
|
|
|
|
|
|
|
XDrawRectangle(blackbox->getXDisplay(), screen->getRootWindow(),
|
|
|
|
screen->getOpGC(), frame.changing.x(), frame.changing.y(),
|
|
|
|
frame.changing.width() - 1, frame.changing.height() - 1);
|
|
|
|
|
|
|
|
screen->showGeometry(gw, gh);
|
|
|
|
|
|
|
|
frame.grab_x = x_root;
|
|
|
|
frame.grab_y = y_root;
|
2002-04-28 11:26:55 +00:00
|
|
|
}
|
2002-04-11 03:20:38 +00:00
|
|
|
|
|
|
|
|
2002-06-21 20:40:14 +00:00
|
|
|
void BlackboxWindow::doResize(int x_root, int y_root) {
|
|
|
|
assert(flags.resizing);
|
|
|
|
assert(blackbox->getChangingWindow() == this);
|
2002-04-28 11:26:55 +00:00
|
|
|
|
2002-06-21 20:40:14 +00:00
|
|
|
XDrawRectangle(blackbox->getXDisplay(), screen->getRootWindow(),
|
|
|
|
screen->getOpGC(), frame.changing.x(), frame.changing.y(),
|
|
|
|
frame.changing.width() - 1, frame.changing.height() - 1);
|
2002-04-28 11:26:55 +00:00
|
|
|
|
2002-06-21 20:40:14 +00:00
|
|
|
int gw, gh;
|
|
|
|
Corner anchor;
|
2002-04-28 11:26:55 +00:00
|
|
|
|
2002-06-21 20:40:14 +00:00
|
|
|
switch (resize_dir) {
|
|
|
|
case BottomLeft:
|
|
|
|
anchor = TopRight;
|
|
|
|
frame.changing.setSize(frame.rect.width() - (x_root - frame.grab_x),
|
|
|
|
frame.rect.height() + (y_root - frame.grab_y));
|
|
|
|
break;
|
|
|
|
case BottomRight:
|
|
|
|
anchor = TopLeft;
|
|
|
|
frame.changing.setSize(frame.rect.width() + (x_root - frame.grab_x),
|
|
|
|
frame.rect.height() + (y_root - frame.grab_y));
|
|
|
|
break;
|
|
|
|
case TopLeft:
|
|
|
|
anchor = BottomRight;
|
|
|
|
frame.changing.setSize(frame.rect.width() - (x_root - frame.grab_x),
|
|
|
|
frame.rect.height() - (y_root - frame.grab_y));
|
|
|
|
break;
|
|
|
|
case TopRight:
|
|
|
|
anchor = BottomLeft;
|
|
|
|
frame.changing.setSize(frame.rect.width() + (x_root - frame.grab_x),
|
|
|
|
frame.rect.height() - (y_root - frame.grab_y));
|
|
|
|
break;
|
2002-04-28 11:26:55 +00:00
|
|
|
|
2002-06-21 20:40:14 +00:00
|
|
|
default:
|
|
|
|
assert(false); // unhandled Corner
|
|
|
|
}
|
|
|
|
|
|
|
|
constrain(anchor, &gw, &gh);
|
2002-04-28 11:26:55 +00:00
|
|
|
|
2002-06-21 20:40:14 +00:00
|
|
|
XDrawRectangle(blackbox->getXDisplay(), screen->getRootWindow(),
|
|
|
|
screen->getOpGC(), frame.changing.x(), frame.changing.y(),
|
|
|
|
frame.changing.width() - 1, frame.changing.height() - 1);
|
2002-04-28 11:26:55 +00:00
|
|
|
|
2002-06-21 20:40:14 +00:00
|
|
|
screen->showGeometry(gw, gh);
|
|
|
|
}
|
2002-04-11 03:20:38 +00:00
|
|
|
|
|
|
|
|
2002-06-21 20:40:14 +00:00
|
|
|
void BlackboxWindow::endResize(void) {
|
|
|
|
assert(flags.resizing);
|
|
|
|
assert(blackbox->getChangingWindow() == this);
|
2002-04-11 03:20:38 +00:00
|
|
|
|
2002-06-21 20:40:14 +00:00
|
|
|
XDrawRectangle(blackbox->getXDisplay(), screen->getRootWindow(),
|
|
|
|
screen->getOpGC(), frame.changing.x(), frame.changing.y(),
|
|
|
|
frame.changing.width() - 1, frame.changing.height() - 1);
|
|
|
|
XUngrabServer(blackbox->getXDisplay());
|
2002-04-11 03:20:38 +00:00
|
|
|
|
2002-06-21 20:40:14 +00:00
|
|
|
// unset maximized state after resized when fully maximized
|
|
|
|
if (flags.maximized == 1)
|
|
|
|
maximize(0);
|
|
|
|
|
|
|
|
flags.resizing = False;
|
|
|
|
blackbox->setChangingWindow(0);
|
2002-05-25 00:29:44 +00:00
|
|
|
|
2002-06-21 20:40:14 +00:00
|
|
|
configure(frame.changing.x(), frame.changing.y(),
|
|
|
|
frame.changing.width(), frame.changing.height());
|
|
|
|
screen->hideGeometry();
|
2002-04-11 03:20:38 +00:00
|
|
|
|
2002-06-21 20:40:14 +00:00
|
|
|
XUngrabPointer(blackbox->getXDisplay(), CurrentTime);
|
|
|
|
|
|
|
|
// if there are any left over motions from the resize, drop them now
|
|
|
|
XSync(blackbox->getXDisplay(), false); // make sure we don't miss any
|
|
|
|
XEvent e;
|
|
|
|
while (XCheckTypedWindowEvent(blackbox->getXDisplay(), frame.window,
|
|
|
|
MotionNotify, &e));
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2002-04-11 03:20:38 +00:00
|
|
|
#ifdef SHAPE
|
2002-05-25 00:29:44 +00:00
|
|
|
void BlackboxWindow::shapeEvent(XShapeEvent *) {
|
|
|
|
if (blackbox->hasShapeExtensions() && flags.shaped) {
|
|
|
|
configureShape();
|
2002-04-11 03:20:38 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
#endif // SHAPE
|
|
|
|
|
|
|
|
|
2002-05-30 08:55:30 +00:00
|
|
|
bool BlackboxWindow::validateClient(void) const {
|
2002-05-25 00:29:44 +00:00
|
|
|
XSync(blackbox->getXDisplay(), False);
|
2002-04-11 03:20:38 +00:00
|
|
|
|
|
|
|
XEvent e;
|
2002-05-25 00:29:44 +00:00
|
|
|
if (XCheckTypedWindowEvent(blackbox->getXDisplay(), client.window,
|
|
|
|
DestroyNotify, &e) ||
|
|
|
|
XCheckTypedWindowEvent(blackbox->getXDisplay(), client.window,
|
|
|
|
UnmapNotify, &e)) {
|
|
|
|
XPutBackEvent(blackbox->getXDisplay(), &e);
|
2002-04-11 03:20:38 +00:00
|
|
|
|
2002-05-25 00:29:44 +00:00
|
|
|
return False;
|
2002-04-11 03:20:38 +00:00
|
|
|
}
|
|
|
|
|
2002-05-25 00:29:44 +00:00
|
|
|
return True;
|
2002-04-11 03:20:38 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
|
2002-05-25 00:29:44 +00:00
|
|
|
void BlackboxWindow::restore(bool remap) {
|
|
|
|
XChangeSaveSet(blackbox->getXDisplay(), client.window, SetModeDelete);
|
|
|
|
XSelectInput(blackbox->getXDisplay(), client.window, NoEventMask);
|
|
|
|
XSelectInput(blackbox->getXDisplay(), frame.plate, NoEventMask);
|
2002-04-11 03:20:38 +00:00
|
|
|
|
|
|
|
restoreGravity();
|
|
|
|
|
2002-05-25 00:29:44 +00:00
|
|
|
XUnmapWindow(blackbox->getXDisplay(), frame.window);
|
|
|
|
XUnmapWindow(blackbox->getXDisplay(), client.window);
|
2002-04-11 03:20:38 +00:00
|
|
|
|
2002-05-25 00:29:44 +00:00
|
|
|
XSetWindowBorderWidth(blackbox->getXDisplay(), client.window, client.old_bw);
|
2002-04-11 03:20:38 +00:00
|
|
|
|
2002-05-25 00:29:44 +00:00
|
|
|
XEvent ev;
|
2002-05-25 15:45:09 +00:00
|
|
|
if (XCheckTypedWindowEvent(blackbox->getXDisplay(), client.window,
|
|
|
|
ReparentNotify, &ev)) {
|
|
|
|
remap = True;
|
|
|
|
} else {
|
2002-05-25 00:29:44 +00:00
|
|
|
// according to the ICCCM - if the client doesn't reparent to
|
|
|
|
// root, then we have to do it for them
|
|
|
|
XReparentWindow(blackbox->getXDisplay(), client.window,
|
|
|
|
screen->getRootWindow(),
|
|
|
|
client.rect.x(), client.rect.y());
|
|
|
|
}
|
2002-05-12 09:15:09 +00:00
|
|
|
|
2002-05-25 00:29:44 +00:00
|
|
|
if (remap) XMapWindow(blackbox->getXDisplay(), client.window);
|
2002-04-11 03:20:38 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
|
2002-05-25 00:29:44 +00:00
|
|
|
// timer for autoraise
|
|
|
|
void BlackboxWindow::timeout(void) {
|
2002-06-29 23:50:04 +00:00
|
|
|
raise();
|
2002-04-11 03:20:38 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
|
2002-05-25 00:29:44 +00:00
|
|
|
void BlackboxWindow::changeBlackboxHints(BlackboxHints *net) {
|
2002-04-11 03:20:38 +00:00
|
|
|
if ((net->flags & AttribShaded) &&
|
2002-05-25 00:29:44 +00:00
|
|
|
((blackbox_attrib.attrib & AttribShaded) !=
|
2002-04-11 03:20:38 +00:00
|
|
|
(net->attrib & AttribShaded)))
|
|
|
|
shade();
|
|
|
|
|
|
|
|
if (flags.visible && // watch out for requests when we can not be seen
|
|
|
|
(net->flags & (AttribMaxVert | AttribMaxHoriz)) &&
|
2002-05-25 00:29:44 +00:00
|
|
|
((blackbox_attrib.attrib & (AttribMaxVert | AttribMaxHoriz)) !=
|
2002-04-11 03:20:38 +00:00
|
|
|
(net->attrib & (AttribMaxVert | AttribMaxHoriz)))) {
|
|
|
|
if (flags.maximized) {
|
|
|
|
maximize(0);
|
|
|
|
} else {
|
|
|
|
int button = 0;
|
|
|
|
|
|
|
|
if ((net->flags & AttribMaxHoriz) && (net->flags & AttribMaxVert))
|
|
|
|
button = ((net->attrib & (AttribMaxHoriz | AttribMaxVert)) ? 1 : 0);
|
|
|
|
else if (net->flags & AttribMaxVert)
|
|
|
|
button = ((net->attrib & AttribMaxVert) ? 2 : 0);
|
|
|
|
else if (net->flags & AttribMaxHoriz)
|
|
|
|
button = ((net->attrib & AttribMaxHoriz) ? 3 : 0);
|
|
|
|
|
|
|
|
maximize(button);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
if ((net->flags & AttribOmnipresent) &&
|
2002-05-25 00:29:44 +00:00
|
|
|
((blackbox_attrib.attrib & AttribOmnipresent) !=
|
2002-04-11 03:20:38 +00:00
|
|
|
(net->attrib & AttribOmnipresent)))
|
|
|
|
stick();
|
|
|
|
|
|
|
|
if ((net->flags & AttribWorkspace) &&
|
2002-05-25 00:29:44 +00:00
|
|
|
(blackbox_attrib.workspace != net->workspace)) {
|
2002-04-11 03:20:38 +00:00
|
|
|
screen->reassociateWindow(this, net->workspace, True);
|
|
|
|
|
2002-05-25 00:29:44 +00:00
|
|
|
if (screen->getCurrentWorkspaceID() != net->workspace) {
|
|
|
|
withdraw();
|
|
|
|
} else {
|
|
|
|
show();
|
2002-06-29 23:50:04 +00:00
|
|
|
raise();
|
2002-05-25 00:29:44 +00:00
|
|
|
}
|
2002-04-11 03:20:38 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
if (net->flags & AttribDecoration) {
|
|
|
|
switch (net->decoration) {
|
|
|
|
case DecorNone:
|
2002-05-25 00:29:44 +00:00
|
|
|
// clear all decorations except close
|
|
|
|
decorations &= Decor_Close;
|
2002-04-11 03:20:38 +00:00
|
|
|
|
|
|
|
break;
|
|
|
|
|
|
|
|
default:
|
|
|
|
case DecorNormal:
|
2002-05-30 08:55:30 +00:00
|
|
|
decorations |= Decor_Titlebar | Decor_Border | Decor_Iconify;
|
|
|
|
|
|
|
|
decorations = ((functions & Func_Resize) && !isTransient() ?
|
|
|
|
decorations | Decor_Handle :
|
|
|
|
decorations &= ~Decor_Handle);
|
|
|
|
decorations = (functions & Func_Maximize ?
|
|
|
|
decorations | Decor_Maximize :
|
|
|
|
decorations &= ~Decor_Maximize);
|
2002-04-11 03:20:38 +00:00
|
|
|
|
|
|
|
break;
|
|
|
|
|
|
|
|
case DecorTiny:
|
2002-05-25 00:29:44 +00:00
|
|
|
decorations |= Decor_Titlebar | Decor_Iconify;
|
2002-05-30 08:55:30 +00:00
|
|
|
decorations &= ~(Decor_Border | Decor_Handle);
|
|
|
|
|
|
|
|
decorations = (functions & Func_Maximize ?
|
|
|
|
decorations | Decor_Maximize :
|
|
|
|
decorations &= ~Decor_Maximize);
|
2002-04-29 07:31:44 +00:00
|
|
|
|
2002-04-11 03:20:38 +00:00
|
|
|
break;
|
|
|
|
|
|
|
|
case DecorTool:
|
2002-05-25 00:29:44 +00:00
|
|
|
decorations |= Decor_Titlebar;
|
2002-05-30 08:55:30 +00:00
|
|
|
decorations &= ~(Decor_Iconify | Decor_Border);
|
|
|
|
|
|
|
|
decorations = ((functions & Func_Resize) && !isTransient() ?
|
|
|
|
decorations | Decor_Handle :
|
|
|
|
decorations &= ~Decor_Handle);
|
|
|
|
decorations = (functions & Func_Maximize ?
|
|
|
|
decorations | Decor_Maximize :
|
|
|
|
decorations &= ~Decor_Maximize);
|
2002-04-11 03:20:38 +00:00
|
|
|
|
|
|
|
break;
|
|
|
|
}
|
2002-05-26 20:53:48 +00:00
|
|
|
|
|
|
|
// we can not be shaded if we lack a titlebar
|
|
|
|
if (flags.shaded && ! (decorations & Decor_Titlebar))
|
|
|
|
shade();
|
|
|
|
|
2002-04-11 03:20:38 +00:00
|
|
|
if (frame.window) {
|
2002-05-25 00:29:44 +00:00
|
|
|
XMapSubwindows(blackbox->getXDisplay(), frame.window);
|
|
|
|
XMapWindow(blackbox->getXDisplay(), frame.window);
|
2002-04-11 03:20:38 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
reconfigure();
|
|
|
|
setState(current_state);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
/*
|
|
|
|
* Set the sizes of all components of the window frame
|
|
|
|
* (the window decorations).
|
|
|
|
* These values are based upon the current style settings and the client
|
2002-05-25 00:29:44 +00:00
|
|
|
* window's dimensions.
|
2002-04-11 03:20:38 +00:00
|
|
|
*/
|
2002-05-25 00:29:44 +00:00
|
|
|
void BlackboxWindow::upsize(void) {
|
2002-04-11 03:20:38 +00:00
|
|
|
frame.bevel_w = screen->getBevelWidth();
|
|
|
|
|
2002-05-25 00:29:44 +00:00
|
|
|
if (decorations & Decor_Border) {
|
2002-04-11 03:20:38 +00:00
|
|
|
frame.border_w = screen->getBorderWidth();
|
2002-05-26 20:25:38 +00:00
|
|
|
if (! isTransient())
|
2002-04-11 03:20:38 +00:00
|
|
|
frame.mwm_border_w = screen->getFrameWidth();
|
|
|
|
else
|
|
|
|
frame.mwm_border_w = 0;
|
|
|
|
} else {
|
|
|
|
frame.mwm_border_w = frame.border_w = 0;
|
|
|
|
}
|
|
|
|
|
2002-05-25 00:29:44 +00:00
|
|
|
if (decorations & Decor_Titlebar) {
|
2002-04-11 03:20:38 +00:00
|
|
|
// the height of the titlebar is based upon the height of the font being
|
|
|
|
// used to display the window's title
|
|
|
|
WindowStyle *style = screen->getWindowStyle();
|
2002-05-16 22:35:59 +00:00
|
|
|
if (i18n.multibyte())
|
2002-04-11 03:20:38 +00:00
|
|
|
frame.title_h = (style->fontset_extents->max_ink_extent.height +
|
2002-05-16 22:35:59 +00:00
|
|
|
(frame.bevel_w * 2) + 2);
|
2002-04-11 03:20:38 +00:00
|
|
|
else
|
|
|
|
frame.title_h = (style->font->ascent + style->font->descent +
|
2002-05-16 22:35:59 +00:00
|
|
|
(frame.bevel_w * 2) + 2);
|
2002-04-11 03:20:38 +00:00
|
|
|
|
|
|
|
frame.label_h = frame.title_h - (frame.bevel_w * 2);
|
2002-05-25 00:29:44 +00:00
|
|
|
frame.button_w = (frame.label_h - 2);
|
|
|
|
|
|
|
|
// set the top frame margin
|
|
|
|
frame.margin.top = frame.border_w + frame.title_h +
|
|
|
|
frame.border_w + frame.mwm_border_w;
|
2002-04-11 03:20:38 +00:00
|
|
|
} else {
|
|
|
|
frame.title_h = 0;
|
|
|
|
frame.label_h = 0;
|
2002-05-25 00:29:44 +00:00
|
|
|
frame.button_w = 0;
|
|
|
|
|
|
|
|
// set the top frame margin
|
|
|
|
frame.margin.top = frame.border_w + frame.mwm_border_w;
|
2002-04-11 03:20:38 +00:00
|
|
|
}
|
|
|
|
|
2002-05-25 00:29:44 +00:00
|
|
|
// set the left/right frame margin
|
|
|
|
frame.margin.left = frame.margin.right = frame.border_w + frame.mwm_border_w;
|
2002-04-11 03:20:38 +00:00
|
|
|
|
2002-05-25 00:29:44 +00:00
|
|
|
if (decorations & Decor_Handle) {
|
2002-04-11 03:20:38 +00:00
|
|
|
frame.grip_w = frame.button_w * 2;
|
2002-05-25 00:29:44 +00:00
|
|
|
frame.handle_h = screen->getHandleWidth();
|
|
|
|
|
|
|
|
// set the bottom frame margin
|
|
|
|
frame.margin.bottom = frame.border_w + frame.handle_h +
|
|
|
|
frame.border_w + frame.mwm_border_w;
|
2002-04-11 03:20:38 +00:00
|
|
|
} else {
|
|
|
|
frame.handle_h = 0;
|
2002-05-25 00:29:44 +00:00
|
|
|
frame.grip_w = 0;
|
|
|
|
|
|
|
|
// set the bottom frame margin
|
|
|
|
frame.margin.bottom = frame.border_w + frame.mwm_border_w;
|
2002-04-11 03:20:38 +00:00
|
|
|
}
|
2002-05-16 22:35:59 +00:00
|
|
|
|
2002-05-28 09:53:11 +00:00
|
|
|
/*
|
|
|
|
We first get the normal dimensions and use this to define the inside_w/h
|
|
|
|
then we modify the height if shading is in effect.
|
|
|
|
If the shade state is not considered then frame.rect gets reset to the
|
|
|
|
normal window size on a reconfigure() call resulting in improper
|
|
|
|
dimensions appearing in move/resize and other events.
|
|
|
|
*/
|
|
|
|
unsigned int
|
|
|
|
height = client.rect.height() + frame.margin.top + frame.margin.bottom,
|
|
|
|
width = client.rect.width() + frame.margin.left + frame.margin.right;
|
|
|
|
|
|
|
|
frame.inside_w = width - (frame.border_w * 2);
|
|
|
|
frame.inside_h = height - (frame.border_w * 2);
|
|
|
|
|
|
|
|
if (flags.shaded)
|
|
|
|
height = frame.title_h + (frame.border_w * 2);
|
|
|
|
frame.rect.setSize(width, height);
|
2002-04-11 03:20:38 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
/*
|
2002-05-25 00:29:44 +00:00
|
|
|
* Calculate the size of the client window and constrain it to the
|
|
|
|
* size specified by the size hints of the client window.
|
|
|
|
*
|
|
|
|
* The logical width and height are placed into pw and ph, if they
|
|
|
|
* are non-zero. Logical size refers to the users perception of
|
2002-05-28 09:53:11 +00:00
|
|
|
* the window size (for example an xterm resizes in cells, not in pixels).
|
2002-05-25 00:29:44 +00:00
|
|
|
*
|
|
|
|
* The physical geometry is placed into frame.changing_{x,y,width,height}.
|
|
|
|
* Physical geometry refers to the geometry of the window in pixels.
|
2002-04-11 03:20:38 +00:00
|
|
|
*/
|
2002-05-25 00:29:44 +00:00
|
|
|
void BlackboxWindow::constrain(Corner anchor, int *pw, int *ph) {
|
|
|
|
// frame.changing represents the requested frame size, we need to
|
|
|
|
// strip the frame margin off and constrain the client size
|
|
|
|
frame.changing.setCoords(frame.changing.left() + frame.margin.left,
|
|
|
|
frame.changing.top() + frame.margin.top,
|
|
|
|
frame.changing.right() - frame.margin.right,
|
|
|
|
frame.changing.bottom() - frame.margin.bottom);
|
|
|
|
|
|
|
|
int dw = frame.changing.width(), dh = frame.changing.height(),
|
|
|
|
base_width = (client.base_width) ? client.base_width : client.min_width,
|
|
|
|
base_height = (client.base_height) ? client.base_height :
|
|
|
|
client.min_height;
|
|
|
|
|
|
|
|
// constrain
|
|
|
|
if (dw < static_cast<signed>(client.min_width)) dw = client.min_width;
|
|
|
|
if (dh < static_cast<signed>(client.min_height)) dh = client.min_height;
|
|
|
|
if (dw > static_cast<signed>(client.max_width)) dw = client.max_width;
|
|
|
|
if (dh > static_cast<signed>(client.max_height)) dh = client.max_height;
|
|
|
|
|
|
|
|
dw -= base_width;
|
|
|
|
dw /= client.width_inc;
|
|
|
|
dh -= base_height;
|
|
|
|
dh /= client.height_inc;
|
|
|
|
|
|
|
|
if (pw) *pw = dw;
|
|
|
|
if (ph) *ph = dh;
|
|
|
|
|
|
|
|
dw *= client.width_inc;
|
|
|
|
dw += base_width;
|
|
|
|
dh *= client.height_inc;
|
|
|
|
dh += base_height;
|
|
|
|
|
|
|
|
frame.changing.setSize(dw, dh);
|
|
|
|
|
|
|
|
// add the frame margin back onto frame.changing
|
|
|
|
frame.changing.setCoords(frame.changing.left() - frame.margin.left,
|
|
|
|
frame.changing.top() - frame.margin.top,
|
|
|
|
frame.changing.right() + frame.margin.right,
|
|
|
|
frame.changing.bottom() + frame.margin.bottom);
|
|
|
|
|
|
|
|
// move frame.changing to the specified anchor
|
2002-06-21 20:40:14 +00:00
|
|
|
int dx = 0,
|
|
|
|
dy = 0;
|
2002-05-25 00:29:44 +00:00
|
|
|
switch (anchor) {
|
|
|
|
case TopLeft:
|
|
|
|
break;
|
2002-04-11 03:20:38 +00:00
|
|
|
|
2002-05-25 00:29:44 +00:00
|
|
|
case TopRight:
|
2002-06-21 20:40:14 +00:00
|
|
|
dx = frame.rect.right() - frame.changing.right();
|
2002-05-25 00:29:44 +00:00
|
|
|
break;
|
2002-06-21 20:40:14 +00:00
|
|
|
|
|
|
|
case BottomLeft:
|
|
|
|
dy = frame.rect.bottom() - frame.changing.bottom();
|
|
|
|
break;
|
|
|
|
|
|
|
|
case BottomRight:
|
|
|
|
dx = frame.rect.right() - frame.changing.right();
|
|
|
|
dy = frame.rect.bottom() - frame.changing.bottom();
|
|
|
|
break;
|
|
|
|
|
|
|
|
default:
|
|
|
|
assert(false); // unhandled corner
|
2002-05-25 00:29:44 +00:00
|
|
|
}
|
2002-06-21 20:40:14 +00:00
|
|
|
frame.changing.setPos(frame.changing.x() + dx, frame.changing.y() + dy);
|
2002-05-25 00:29:44 +00:00
|
|
|
}
|
2002-04-11 03:20:38 +00:00
|
|
|
|
|
|
|
|
2002-05-25 00:29:44 +00:00
|
|
|
int WindowStyle::doJustify(const char *text, int &start_pos,
|
|
|
|
unsigned int max_length, unsigned int modifier,
|
|
|
|
bool multibyte) const {
|
|
|
|
size_t text_len = strlen(text);
|
|
|
|
unsigned int length;
|
2002-04-11 03:20:38 +00:00
|
|
|
|
2002-05-25 00:29:44 +00:00
|
|
|
do {
|
|
|
|
if (multibyte) {
|
|
|
|
XRectangle ink, logical;
|
|
|
|
XmbTextExtents(fontset, text, text_len, &ink, &logical);
|
|
|
|
length = logical.width;
|
|
|
|
} else {
|
|
|
|
length = XTextWidth(font, text, text_len);
|
|
|
|
}
|
|
|
|
length += modifier;
|
|
|
|
} while (length > max_length && text_len-- > 0);
|
2002-04-11 03:20:38 +00:00
|
|
|
|
2002-05-25 00:29:44 +00:00
|
|
|
switch (justify) {
|
|
|
|
case RightJustify:
|
|
|
|
start_pos += max_length - length;
|
|
|
|
break;
|
2002-04-11 03:20:38 +00:00
|
|
|
|
2002-05-25 00:29:44 +00:00
|
|
|
case CenterJustify:
|
|
|
|
start_pos += (max_length - length) / 2;
|
|
|
|
break;
|
2002-04-11 03:20:38 +00:00
|
|
|
|
2002-05-25 00:29:44 +00:00
|
|
|
case LeftJustify:
|
|
|
|
default:
|
|
|
|
break;
|
|
|
|
}
|
2002-04-11 03:20:38 +00:00
|
|
|
|
2002-05-25 00:29:44 +00:00
|
|
|
return text_len;
|
|
|
|
}
|
2002-04-11 03:20:38 +00:00
|
|
|
|
|
|
|
|
2002-05-25 00:29:44 +00:00
|
|
|
BWindowGroup::BWindowGroup(Blackbox *b, Window _group)
|
|
|
|
: blackbox(b), group(_group) {
|
2002-05-28 09:53:11 +00:00
|
|
|
XWindowAttributes wattrib;
|
|
|
|
if (! XGetWindowAttributes(blackbox->getXDisplay(), group, &wattrib)) {
|
|
|
|
// group window doesn't seem to exist anymore
|
|
|
|
delete this;
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
/*
|
|
|
|
watch for destroy notify on the group window (in addition to
|
|
|
|
any other events we are looking for)
|
|
|
|
|
|
|
|
since some managed windows can also be window group controllers,
|
|
|
|
we need to make sure that we don't clobber the event mask for the
|
|
|
|
managed window
|
|
|
|
*/
|
|
|
|
XSelectInput(blackbox->getXDisplay(), group,
|
|
|
|
wattrib.your_event_mask | StructureNotifyMask);
|
|
|
|
|
2002-05-25 00:29:44 +00:00
|
|
|
blackbox->saveGroupSearch(group, this);
|
2002-04-11 03:20:38 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
|
2002-05-25 00:29:44 +00:00
|
|
|
BWindowGroup::~BWindowGroup(void) {
|
|
|
|
blackbox->removeGroupSearch(group);
|
|
|
|
}
|
|
|
|
|
2002-04-11 03:20:38 +00:00
|
|
|
|
2002-05-25 00:29:44 +00:00
|
|
|
BlackboxWindow *
|
|
|
|
BWindowGroup::find(BScreen *screen, bool allow_transients) const {
|
|
|
|
BlackboxWindow *ret = blackbox->getFocusedWindow();
|
2002-04-11 03:20:38 +00:00
|
|
|
|
2002-05-25 00:29:44 +00:00
|
|
|
// does the focus window match (or any transient_fors)?
|
|
|
|
while (ret) {
|
|
|
|
if (ret->getScreen() == screen && ret->getGroupWindow() == group) {
|
|
|
|
if (ret->isTransient() && allow_transients) break;
|
|
|
|
else if (! ret->isTransient()) break;
|
|
|
|
}
|
2002-04-11 03:20:38 +00:00
|
|
|
|
2002-05-25 00:29:44 +00:00
|
|
|
ret = ret->getTransientFor();
|
|
|
|
}
|
2002-04-11 03:20:38 +00:00
|
|
|
|
2002-05-25 00:29:44 +00:00
|
|
|
if (ret) return ret;
|
2002-04-11 03:20:38 +00:00
|
|
|
|
2002-05-25 00:29:44 +00:00
|
|
|
// the focus window didn't match, look in the group's window list
|
|
|
|
BlackboxWindowList::const_iterator it, end = windowList.end();
|
|
|
|
for (it = windowList.begin(); it != end; ++it) {
|
|
|
|
ret = *it;
|
|
|
|
if (ret->getScreen() == screen && ret->getGroupWindow() == group) {
|
|
|
|
if (ret->isTransient() && allow_transients) break;
|
|
|
|
else if (! ret->isTransient()) break;
|
|
|
|
}
|
|
|
|
}
|
2002-05-16 22:35:59 +00:00
|
|
|
|
2002-05-25 00:29:44 +00:00
|
|
|
return ret;
|
2002-04-11 03:20:38 +00:00
|
|
|
}
|