WINDOWS GET FRAMES FRAME SHOW UP THEY WORK HUZZAH SOON THEYLL BE LIKE OLD TIMES!

This commit is contained in:
Dana Jansens 2002-11-10 04:08:26 +00:00
parent f2ae1c3b17
commit b9cac2146e
6 changed files with 313 additions and 43 deletions

View file

@ -15,7 +15,7 @@ bin_PROGRAMS= openbox3
openbox3_LDADD=../otk/libotk.a @LIBINTL@
openbox3_SOURCES= client.cc screen.cc openbox.cc \
openbox3_SOURCES= client.cc frame.cc screen.cc openbox.cc \
bbwindow.cc workspace.cc blackbox.cc \
main.cc xeventhandler.cc

View file

@ -1,5 +1,9 @@
// -*- mode: C++; indent-tabs-mode: nil; c-basic-offset: 2; -*-
#ifdef HAVE_CONFIG_H
# include "../config.h"
#endif
#include "client.hh"
#include "screen.hh"
#include "openbox.hh"
@ -18,8 +22,8 @@ extern "C" {
namespace ob {
OBClient::OBClient(Window window)
: _window(window)
OBClient::OBClient(int screen, Window window)
: _screen(screen), _window(window)
{
assert(window);
@ -78,6 +82,7 @@ OBClient::OBClient(Window window)
updateIconTitle();
updateClass();
/*
#ifdef DEBUG
printf("Mapped window: 0x%lx\n"
" title: \t%s\t icon title: \t%s\n"
@ -123,6 +128,7 @@ OBClient::OBClient(Window window)
_floating ? "yes" : "no",
_positioned ? "yes" : "no");
#endif
*/
}

View file

@ -18,6 +18,8 @@ extern "C" {
namespace ob {
class OBFrame;
//! Maintains the state of a client window.
/*!
OBClient maintains the state of a client window. The state consists of the
@ -32,6 +34,10 @@ namespace ob {
*/
class OBClient {
public:
//! The frame window which decorates around the client window
OBFrame *frame;
//! Possible window types
enum WindowType { Type_Desktop, //!< A desktop (bottom-most window)
Type_Dock, //!< A dock bar/panel window
@ -107,7 +113,14 @@ public:
State_Toggle //!< _NET_WM_STATE_TOGGLE
};
//! The event mask to grab on client windows
static const long event_mask = PropertyChangeMask | FocusChangeMask |
StructureNotifyMask;
private:
//! The screen number on which the client resides
int _screen;
//! The actual window that this class is wrapping up
Window _window;
@ -272,11 +285,15 @@ public:
//! Constructs a new OBClient object around a specified window id
/*!
@param window The window id that the OBClient class should handle
@param screen The screen on which the window resides
*/
OBClient(Window window);
OBClient(int screen, Window window);
//! Destroys the OBClient object
virtual ~OBClient();
//! Returns the screen on which the clien resides
inline int screen() const { return _screen; }
//! Returns the window id that the OBClient object is handling
inline Window window() const { return _window; }

149
src/frame.cc Normal file
View file

@ -0,0 +1,149 @@
// -*- mode: C++; indent-tabs-mode: nil; c-basic-offset: 2; -*-
#ifdef HAVE_CONFIG_H
# include "../config.h"
#endif
#include "frame.hh"
#include "client.hh"
#include "otk/display.hh"
namespace ob {
OBFrame::OBFrame(const OBClient *client, const otk::Style *style)
: _client(client),
_screen(otk::OBDisplay::screenInfo(client->screen()))
{
assert(client);
assert(style);
_style = 0;
loadStyle(style);
_window = createFrame();
assert(_window);
grabClient();
}
OBFrame::~OBFrame()
{
releaseClient(false);
}
void OBFrame::loadStyle(const otk::Style *style)
{
assert(style);
// if a style was previously set, then 'replace' is true, cause we're
// replacing a style
// NOTE: if this is false, then DO NOT DO SHIT WITH _window, it doesnt exist
bool replace = (_style);
if (replace) {
// XXX: do shit here whatever
}
_style = style;
// XXX: load shit like this from the style!
_size.left = _size.top = _size.bottom = _size.right = 2;
if (replace) {
XSetWindowBorderWidth(otk::OBDisplay::display, _window,
_style->getBorderWidth());
// XXX: make everything redraw
}
}
void OBFrame::resize()
{
XResizeWindow(otk::OBDisplay::display, _window,
_size.left + _size.right + _client->area().width(),
_size.top + _size.bottom + _client->area().height());
// XXX: more is gunna have to happen here
}
void OBFrame::shape()
{
// XXX: if shaped, shape the frame to the client..
}
void OBFrame::grabClient()
{
XGrabServer(otk::OBDisplay::display);
// select the event mask on the frame
XSelectInput(otk::OBDisplay::display, _window, SubstructureRedirectMask);
// reparent the client to the frame
XSelectInput(otk::OBDisplay::display, _client->window(),
OBClient::event_mask & ~StructureNotifyMask);
XReparentWindow(otk::OBDisplay::display, _client->window(), _window, 0, 0);
XSelectInput(otk::OBDisplay::display, _client->window(),
OBClient::event_mask);
// raise the client above the frame
XRaiseWindow(otk::OBDisplay::display, _client->window());
// map the client so it maps when the frame does
XMapWindow(otk::OBDisplay::display, _client->window());
XUngrabServer(otk::OBDisplay::display);
resize();
shape();
}
void OBFrame::releaseClient(bool remap)
{
// check if the app has already reparented its window to the root window
XEvent ev;
if (XCheckTypedWindowEvent(otk::OBDisplay::display, _client->window(),
ReparentNotify, &ev)) {
remap = true; // XXX: why do we remap the window if they already
// reparented to root?
} else {
// according to the ICCCM - if the client doesn't reparent to
// root, then we have to do it for them
XReparentWindow(otk::OBDisplay::display, _client->window(),
_screen->getRootWindow(),
_client->area().x(), _client->area().y());
}
// if we want to remap the window, do so now
if (remap)
XMapWindow(otk::OBDisplay::display, _client->window());
}
Window OBFrame::createFrame()
{
XSetWindowAttributes attrib_create;
unsigned long create_mask = CWBackPixmap | CWBorderPixel | CWColormap |
CWOverrideRedirect | CWEventMask;
attrib_create.background_pixmap = None;
attrib_create.colormap = _screen->getColormap();
attrib_create.override_redirect = True;
attrib_create.event_mask = EnterWindowMask | LeaveWindowMask | ButtonPress;
/*
We catch button presses because other wise they get passed down to the
root window, which will then cause root menus to show when you click the
window's frame.
*/
return XCreateWindow(otk::OBDisplay::display, _screen->getRootWindow(),
0, 0, 1, 1, _style->getBorderWidth(),
_screen->getDepth(), InputOutput, _screen->getVisual(),
create_mask, &attrib_create);
}
}

75
src/frame.hh Normal file
View file

@ -0,0 +1,75 @@
// -*- mode: C++; indent-tabs-mode: nil; c-basic-offset: 2; -*-
#ifndef __frame_hh
#define __frame_hh
/*! @file frame.hh
*/
extern "C" {
#include <X11/Xlib.h>
}
#include <string>
#include "otk/strut.hh"
#include "otk/rect.hh"
#include "otk/screeninfo.hh"
#include "otk/style.hh"
namespace ob {
class OBClient;
//! Holds and decorates a frame around an OBClient (client window)
/*!
*/
class OBFrame {
private:
const OBClient *_client;
const otk::ScreenInfo *_screen;
//! The style to use for size and display the decorations
const otk::Style *_style;
//! The window id of the base frame window
Window _window;
//! The size of the frame on each side of the client window
otk::Strut _size;
//! Creates the base frame window
Window createFrame();
//! Reparents the client window from the root window onto the frame
void grabClient();
//! Reparents the client window back to the root window
/*!
@param remap Re-map the client window when we're done reparenting?
*/
void releaseClient(bool remap);
public:
//! Constructs an OBFrame object, and reparents the client to itself
/*!
@param client The client window which will be decorated by the new OBFrame
@param style The style to use to decorate the frame
*/
OBFrame(const OBClient *client, const otk::Style *style);
//! Destroys the OBFrame object
virtual ~OBFrame();
//! Load a style to decorate the frame with
void loadStyle(const otk::Style *style);
//! Size the frame to the client
void resize();
//! Shape the frame window to the client window
void shape();
//! Returns the frame's most-parent window, which is a child of the root
//! window
inline Window window() const { return _window; }
};
}
#endif // __frame_hh

View file

@ -2,10 +2,15 @@
#include "xeventhandler.hh"
#include "client.hh"
#include "frame.hh"
#include "openbox.hh"
#include "otk/display.hh"
#include "otk/rect.hh"
// XXX: REMOVE THIS SOON!!#!
#include "blackbox.hh"
#include "screen.hh"
extern "C" {
#include <X11/Xlib.h>
#include <X11/Xutil.h>
@ -119,7 +124,7 @@ void OBXEventHandler::configureRequest(const XConfigureRequestEvent &e)
// XXX: put this into the OBScreen or OBClient class!
static void manageWindow(Window window)
static void manageWindow(int screen, Window window)
{
OBClient *client = 0;
XWMHints *wmhint;
@ -139,15 +144,14 @@ static void manageWindow(Window window)
}
// choose the events we want to receive on the CLIENT window
attrib_set.event_mask = PropertyChangeMask | FocusChangeMask |
StructureNotifyMask;
attrib_set.event_mask = OBClient::event_mask;
attrib_set.do_not_propagate_mask = ButtonPressMask | ButtonReleaseMask |
ButtonMotionMask;
XChangeWindowAttributes(otk::OBDisplay::display, window,
CWEventMask|CWDontPropagate, &attrib_set);
// create the OBClient class, which gets all of the hints on the window
Openbox::instance->addClient(window, client = new OBClient(window));
Openbox::instance->addClient(window, client = new OBClient(screen, window));
// we dont want a border on the client
XSetWindowBorderWidth(otk::OBDisplay::display, window, 0);
@ -159,14 +163,15 @@ static void manageWindow(Window window)
if (!client->positionRequested()) {
// XXX: position the window intelligenty
}
// XXX: store a style somewheres cooler!!
otk::Style *style = ((Blackbox*)Openbox::instance)->
searchScreen(RootWindow(otk::OBDisplay::display, screen))->
getWindowStyle();
client->frame = new OBFrame(client, style);
// XXX: grab server, reparent client to the frame, ungrab server
// XXX: if shaped, shape the frame..
// XXX: if on the current desktop..
/// XMapSubwindows(otk::OBDisplay::display, FRAMEWINDOW);
XMapWindow(otk::OBDisplay::display, window);
XMapWindow(otk::OBDisplay::display, client->frame->window());
// XXX: handle any requested states such as shaded/maximized
}
@ -174,46 +179,27 @@ static void manageWindow(Window window)
// XXX: move this to the OBScreen or OBClient class!
static void unmanageWindow(OBClient *client)
{
bool remap = false; // remap the window when we're done?
Window window = client->window();
OBFrame *frame = client->frame;
// XXX: pass around focus if this window was focused
// remove the window from our save set
XChangeSaveSet(otk::OBDisplay::display, window, SetModeDelete);
XChangeSaveSet(otk::OBDisplay::display, client->window(), SetModeDelete);
// we dont want events no more
XSelectInput(otk::OBDisplay::display, window, NoEventMask);
XSelectInput(otk::OBDisplay::display, client->window(), NoEventMask);
// XXX: XUnmapWindow(otk::OBDisplay::display, FRAME);
XUnmapWindow(otk::OBDisplay::display, window);
XUnmapWindow(otk::OBDisplay::display, frame->window());
// we dont want a border on the client
XSetWindowBorderWidth(otk::OBDisplay::display, window,client->borderWidth());
XSetWindowBorderWidth(otk::OBDisplay::display, client->window(),
client->borderWidth());
// remove the client class from the search list
Openbox::instance->removeClient(window);
Openbox::instance->removeClient(client->window());
// check if the app has already reparented its window to the root window
XEvent ev;
if (XCheckTypedWindowEvent(otk::OBDisplay::display, window, ReparentNotify,
&ev)) {
remap = true; // XXX: why do we remap the window if they already
// reparented to root?
} else {
// according to the ICCCM - if the client doesn't reparent to
// root, then we have to do it for them
XReparentWindow(otk::OBDisplay::display, window,
RootWindow(otk::OBDisplay::display,
DefaultScreen(otk::OBDisplay::display)),
// XXX: screen->getRootWindow(),
client->area().x(), client->area().y());
}
// if we want to remap the window, do so now
if (remap)
XMapWindow(otk::OBDisplay::display, window);
delete client->frame;
client->frame = 0;
delete client;
}
@ -229,7 +215,44 @@ void OBXEventHandler::mapRequest(const XMapRequestEvent &e)
if (client) {
// XXX: uniconify and/or unshade the window
} else {
manageWindow(e.window);
int screen = INT_MAX;
for (int i = 0; i < ScreenCount(otk::OBDisplay::display); ++i)
if (otk::OBDisplay::screenInfo(i)->getRootWindow() == e.parent) {
screen = i;
break;
}
if (screen >= ScreenCount(otk::OBDisplay::display)) {
/*
we got a map request for a window who's parent isn't root. this
can happen in only one circumstance:
a client window unmapped a managed window, and then remapped it
somewhere between unmapping the client window and reparenting it
to root.
regardless of how it happens, we need to find the screen that
the window is on
*/
XWindowAttributes wattrib;
if (! XGetWindowAttributes(otk::OBDisplay::display, e.window,
&wattrib)) {
// failed to get the window attributes, perhaps the window has
// now been destroyed?
return;
}
for (int i = 0; i < ScreenCount(otk::OBDisplay::display); ++i)
if (otk::OBDisplay::screenInfo(i)->getRootWindow() == wattrib.root) {
screen = i;
break;
}
}
assert(screen < ScreenCount(otk::OBDisplay::display));
manageWindow(screen, e.window);
}
/*