ede/evoke/Composite.cpp

1363 lines
34 KiB
C++
Raw Normal View History

/*
* $Id$
*
* Evoke, head honcho of everything
* Part of Equinox Desktop Environment (EDE).
* Based on xcompmgr (c) 2003 Keith Packard.
* Copyright (c) 2007 EDE Authors.
*
* This program is licensed under terms of the
* GNU General Public License version 2 or newer.
* See COPYING for details.
*/
#include "Composite.h"
#include "ClassHack.h"
#include <edelib/Debug.h>
#include <FL/x.h>
#include <FL/Fl.h>
#include <string.h> // memcpy
#include <stdlib.h> // malloc, realloc
#include <X11/extensions/Xcomposite.h>
#include <X11/extensions/Xrender.h>
#define TRANSLUCENT 0xe0000000
#define OPAQUE 0xffffffff
#define REFRESH_TIMEOUT 0.05
#define WIN_MODE_SOLID 0
#define WIN_MODE_TRANS 1
#define WIN_MODE_ARGB 2
static int render_error;
static int damage_error;
static int xfixes_error;
static bool have_name_pixmap = false;
static int composite_opcode;
static int damage_event;
static bool another_is_running;
Atom _XA_NET_WM_WINDOW_OPACITY;
Atom _XA_NET_WM_WINDOW_TYPE;
Atom _XA_NET_WM_WINDOW_TYPE_DESKTOP;
Atom _XA_NET_WM_WINDOW_TYPE_DOCK;
Atom _XA_NET_WM_WINDOW_TYPE_TOOLBAR;
Atom _XA_NET_WM_WINDOW_TYPE_MENU;
Atom _XA_NET_WM_WINDOW_TYPE_UTILITY;
Atom _XA_NET_WM_WINDOW_TYPE_SPLASH;
Atom _XA_NET_WM_WINDOW_TYPE_DIALOG;
Atom _XA_NET_WM_WINDOW_TYPE_NORMAL;
static char* backgroundProps[] = {
"_XROOTPMAP_ID",
"_XSETROOT_ID",
0
};
//#define HAVE_NAME_WINDOW_PIXMAP 1
struct CWindow {
Window id;
#if HAVE_NAME_WINDOW_PIXMAP
Pixmap pixmap;
#endif
XWindowAttributes attr;
int mode;
int damaged;
Damage damage;
Picture picture;
Picture picture_alpha;
Picture picture_shadow;
XserverRegion border_size;
XserverRegion extents;
Picture shadow;
int shadow_dx;
int shadow_dy;
int shadow_w;
int shadow_h;
unsigned int opacity;
Atom window_type;
unsigned long damage_sequence; // sequence when damage was created
// for drawing translucent windows
XserverRegion border_clip;
};
XserverRegion allDamage;
bool fadeWindows = true;
bool clipChanged = false;
bool excludeDockShadows = true;
Picture rootBuffer = 0;
Picture rootPicture = 0;
Picture rootTile = 0;
Picture blackPicture = 0;
int shadowRadius = 12;
int shadowOffsetX = -15;
int shadowOffsetY = -15;
double shadowOpacity = .75;
bool hasNamePixmap = true;
A lot of changes, especially the ways how screen is repainted (in composite). Composite will now draw only damaged regions, and their damage is (now) correctly reported, mostly due changes in main FLTK loop. Also there are two ways how evoke will be running: if USE_FLTK_LOOP_EMULATION is defined (default yes), it will fully emulate FLTK loop (as done before). Oposite way (without emulation) it will relay on FLTK message passing, but it is very unpredictable since FLTK will sometime miss SelectionClear events (XSETTINGS relay on it), probably due large XDamageNotify throttling. When emulation is used, there are no such problems since all events are processed before they are routed to FLTK. In composite is added another way of repainting (when USE_CHECK is defined), and it will relay on Fl::add_check() function; there are some differences between this function and timer used for screen refresh. Timer will try to refresh it every XX ms and when there are large number of XDamageNotify reports, this will not be suitable for movements smoothing on the screen; on other hand add_check() will call callback every time when event is processed, which brings smooth movements. For now only timer is used untill I finish compositing stuff. Also composite will handle messages from it's own add_handler() since (somehow), all pending XDamageNotify events will not be correctly reported inside EvokeService handler. And about splash... splash will now keep it's window at the top, no matter what window is raised. This is a small hack until I implement _NET_WM_WINDOW_TYPE_SPLASH in edewm (I don't have to say that this hack works for all wm's I tested :P). Sound from splash is removed; reason for this is when evoke starts childs (only when X session was started), device descriptors will be used by childs too making sound device unusable and marked as busy. This can be solved by using better sound library, which is story for itself...
2008-01-14 15:50:30 +03:00
#define DO_BETTER_REPAINT 1
void idle_cb(void* c) {
Composite* comp = (Composite*)c;
A lot of changes, especially the ways how screen is repainted (in composite). Composite will now draw only damaged regions, and their damage is (now) correctly reported, mostly due changes in main FLTK loop. Also there are two ways how evoke will be running: if USE_FLTK_LOOP_EMULATION is defined (default yes), it will fully emulate FLTK loop (as done before). Oposite way (without emulation) it will relay on FLTK message passing, but it is very unpredictable since FLTK will sometime miss SelectionClear events (XSETTINGS relay on it), probably due large XDamageNotify throttling. When emulation is used, there are no such problems since all events are processed before they are routed to FLTK. In composite is added another way of repainting (when USE_CHECK is defined), and it will relay on Fl::add_check() function; there are some differences between this function and timer used for screen refresh. Timer will try to refresh it every XX ms and when there are large number of XDamageNotify reports, this will not be suitable for movements smoothing on the screen; on other hand add_check() will call callback every time when event is processed, which brings smooth movements. For now only timer is used untill I finish compositing stuff. Also composite will handle messages from it's own add_handler() since (somehow), all pending XDamageNotify events will not be correctly reported inside EvokeService handler. And about splash... splash will now keep it's window at the top, no matter what window is raised. This is a small hack until I implement _NET_WM_WINDOW_TYPE_SPLASH in edewm (I don't have to say that this hack works for all wm's I tested :P). Sound from splash is removed; reason for this is when evoke starts childs (only when X session was started), device descriptors will be used by childs too making sound device unusable and marked as busy. This can be solved by using better sound library, which is story for itself...
2008-01-14 15:50:30 +03:00
#ifdef DO_BETTER_REPAINT
if(allDamage != None) {
comp->paint_all(allDamage);
XFixesDestroyRegion(fl_display, allDamage);
allDamage = None;
clipChanged = false;
}
#else
comp->paint_all(allDamage);
A lot of changes, especially the ways how screen is repainted (in composite). Composite will now draw only damaged regions, and their damage is (now) correctly reported, mostly due changes in main FLTK loop. Also there are two ways how evoke will be running: if USE_FLTK_LOOP_EMULATION is defined (default yes), it will fully emulate FLTK loop (as done before). Oposite way (without emulation) it will relay on FLTK message passing, but it is very unpredictable since FLTK will sometime miss SelectionClear events (XSETTINGS relay on it), probably due large XDamageNotify throttling. When emulation is used, there are no such problems since all events are processed before they are routed to FLTK. In composite is added another way of repainting (when USE_CHECK is defined), and it will relay on Fl::add_check() function; there are some differences between this function and timer used for screen refresh. Timer will try to refresh it every XX ms and when there are large number of XDamageNotify reports, this will not be suitable for movements smoothing on the screen; on other hand add_check() will call callback every time when event is processed, which brings smooth movements. For now only timer is used untill I finish compositing stuff. Also composite will handle messages from it's own add_handler() since (somehow), all pending XDamageNotify events will not be correctly reported inside EvokeService handler. And about splash... splash will now keep it's window at the top, no matter what window is raised. This is a small hack until I implement _NET_WM_WINDOW_TYPE_SPLASH in edewm (I don't have to say that this hack works for all wm's I tested :P). Sound from splash is removed; reason for this is when evoke starts childs (only when X session was started), device descriptors will be used by childs too making sound device unusable and marked as busy. This can be solved by using better sound library, which is story for itself...
2008-01-14 15:50:30 +03:00
if(allDamage != None) {
XFixesDestroyRegion(fl_display, allDamage);
allDamage = None;
clipChanged = false;
}
#endif
A lot of changes, especially the ways how screen is repainted (in composite). Composite will now draw only damaged regions, and their damage is (now) correctly reported, mostly due changes in main FLTK loop. Also there are two ways how evoke will be running: if USE_FLTK_LOOP_EMULATION is defined (default yes), it will fully emulate FLTK loop (as done before). Oposite way (without emulation) it will relay on FLTK message passing, but it is very unpredictable since FLTK will sometime miss SelectionClear events (XSETTINGS relay on it), probably due large XDamageNotify throttling. When emulation is used, there are no such problems since all events are processed before they are routed to FLTK. In composite is added another way of repainting (when USE_CHECK is defined), and it will relay on Fl::add_check() function; there are some differences between this function and timer used for screen refresh. Timer will try to refresh it every XX ms and when there are large number of XDamageNotify reports, this will not be suitable for movements smoothing on the screen; on other hand add_check() will call callback every time when event is processed, which brings smooth movements. For now only timer is used untill I finish compositing stuff. Also composite will handle messages from it's own add_handler() since (somehow), all pending XDamageNotify events will not be correctly reported inside EvokeService handler. And about splash... splash will now keep it's window at the top, no matter what window is raised. This is a small hack until I implement _NET_WM_WINDOW_TYPE_SPLASH in edewm (I don't have to say that this hack works for all wm's I tested :P). Sound from splash is removed; reason for this is when evoke starts childs (only when X session was started), device descriptors will be used by childs too making sound device unusable and marked as busy. This can be solved by using better sound library, which is story for itself...
2008-01-14 15:50:30 +03:00
#ifndef USE_CHECK
Fl::repeat_timeout(REFRESH_TIMEOUT, idle_cb, c);
A lot of changes, especially the ways how screen is repainted (in composite). Composite will now draw only damaged regions, and their damage is (now) correctly reported, mostly due changes in main FLTK loop. Also there are two ways how evoke will be running: if USE_FLTK_LOOP_EMULATION is defined (default yes), it will fully emulate FLTK loop (as done before). Oposite way (without emulation) it will relay on FLTK message passing, but it is very unpredictable since FLTK will sometime miss SelectionClear events (XSETTINGS relay on it), probably due large XDamageNotify throttling. When emulation is used, there are no such problems since all events are processed before they are routed to FLTK. In composite is added another way of repainting (when USE_CHECK is defined), and it will relay on Fl::add_check() function; there are some differences between this function and timer used for screen refresh. Timer will try to refresh it every XX ms and when there are large number of XDamageNotify reports, this will not be suitable for movements smoothing on the screen; on other hand add_check() will call callback every time when event is processed, which brings smooth movements. For now only timer is used untill I finish compositing stuff. Also composite will handle messages from it's own add_handler() since (somehow), all pending XDamageNotify events will not be correctly reported inside EvokeService handler. And about splash... splash will now keep it's window at the top, no matter what window is raised. This is a small hack until I implement _NET_WM_WINDOW_TYPE_SPLASH in edewm (I don't have to say that this hack works for all wm's I tested :P). Sound from splash is removed; reason for this is when evoke starts childs (only when X session was started), device descriptors will be used by childs too making sound device unusable and marked as busy. This can be solved by using better sound library, which is story for itself...
2008-01-14 15:50:30 +03:00
#endif
}
int xerror_handler(Display* display, XErrorEvent* xev) {
if(xev->request_code == composite_opcode && xev->minor_code == X_CompositeRedirectSubwindows) {
EWARNING(ESTRLOC ": Another composite manager is running\n");
another_is_running = true;
return 1;
}
char* name = NULL;
int o = xev->error_code - xfixes_error;
switch(o) {
case BadRegion:
name = "BadRegion";
break;
default:
break;
}
o = xev->error_code - damage_error;
switch(o) {
case BadDamage:
name = "BadDamage";
break;
default:
break;
}
o = xev->error_code - render_error;
switch(o) {
case BadPictFormat:
name = "BadPictFormat";
break;
case BadPicture:
name = "BadPicture";
break;
case BadPictOp:
name = "BadPictOp";
break;
case BadGlyphSet:
name = "BadGlyphSet";
break;
case BadGlyph:
name = "BadGlyph";
break;
default:
break;
}
A lot of changes, especially the ways how screen is repainted (in composite). Composite will now draw only damaged regions, and their damage is (now) correctly reported, mostly due changes in main FLTK loop. Also there are two ways how evoke will be running: if USE_FLTK_LOOP_EMULATION is defined (default yes), it will fully emulate FLTK loop (as done before). Oposite way (without emulation) it will relay on FLTK message passing, but it is very unpredictable since FLTK will sometime miss SelectionClear events (XSETTINGS relay on it), probably due large XDamageNotify throttling. When emulation is used, there are no such problems since all events are processed before they are routed to FLTK. In composite is added another way of repainting (when USE_CHECK is defined), and it will relay on Fl::add_check() function; there are some differences between this function and timer used for screen refresh. Timer will try to refresh it every XX ms and when there are large number of XDamageNotify reports, this will not be suitable for movements smoothing on the screen; on other hand add_check() will call callback every time when event is processed, which brings smooth movements. For now only timer is used untill I finish compositing stuff. Also composite will handle messages from it's own add_handler() since (somehow), all pending XDamageNotify events will not be correctly reported inside EvokeService handler. And about splash... splash will now keep it's window at the top, no matter what window is raised. This is a small hack until I implement _NET_WM_WINDOW_TYPE_SPLASH in edewm (I don't have to say that this hack works for all wm's I tested :P). Sound from splash is removed; reason for this is when evoke starts childs (only when X session was started), device descriptors will be used by childs too making sound device unusable and marked as busy. This can be solved by using better sound library, which is story for itself...
2008-01-14 15:50:30 +03:00
//EDEBUG(ESTRLOC ": (%s) : error %i request %i minor %i serial %i\n",
// (name ? name : "unknown"), xev->error_code, xev->request_code, xev->minor_code, xev->serial);
#if 0
char buff[128];
XGetErrorDatabaseText(fl_display, "XlibMessage", "XError", "", buff, 128);
EDEBUG("%s", buff);
XGetErrorText(fl_display, xev->error_code, buff, 128);
EDEBUG(" :%s\n", buff);
XGetErrorDatabaseText(fl_display, "XlibMessage", "MajorCode", "%d", buff, 128);
EDEBUG(" ");
EDEBUG(buff, xev->request_code);
EDEBUG("\n");
XGetErrorDatabaseText(fl_display, "XlibMessage", "MinorCode", "%d", buff, 128);
EDEBUG(" ");
EDEBUG(buff, xev->minor_code);
EDEBUG("\n");
XGetErrorDatabaseText(fl_display, "XlibMessage", "ResourceID", "%d", buff, 128);
EDEBUG(" ");
EDEBUG(buff, xev->resourceid);
EDEBUG("\n");
#endif
return 0;
}
void set_ignore(unsigned long sequence) {
// TODO
}
unsigned int get_opacity_property(CWindow* win, unsigned int dflt) {
Atom actual;
int format;
unsigned long n, left;
unsigned char* data = NULL;
int ret = XGetWindowProperty(fl_display, win->id, _XA_NET_WM_WINDOW_OPACITY, 0L, 1L, False,
XA_CARDINAL, &actual, &format, &n, &left, &data);
if(ret == Success && data != NULL) {
unsigned int p;
// TODO: replace memcpy call
memcpy(&p, data, sizeof(unsigned int));
XFree(data);
A lot of changes, especially the ways how screen is repainted (in composite). Composite will now draw only damaged regions, and their damage is (now) correctly reported, mostly due changes in main FLTK loop. Also there are two ways how evoke will be running: if USE_FLTK_LOOP_EMULATION is defined (default yes), it will fully emulate FLTK loop (as done before). Oposite way (without emulation) it will relay on FLTK message passing, but it is very unpredictable since FLTK will sometime miss SelectionClear events (XSETTINGS relay on it), probably due large XDamageNotify throttling. When emulation is used, there are no such problems since all events are processed before they are routed to FLTK. In composite is added another way of repainting (when USE_CHECK is defined), and it will relay on Fl::add_check() function; there are some differences between this function and timer used for screen refresh. Timer will try to refresh it every XX ms and when there are large number of XDamageNotify reports, this will not be suitable for movements smoothing on the screen; on other hand add_check() will call callback every time when event is processed, which brings smooth movements. For now only timer is used untill I finish compositing stuff. Also composite will handle messages from it's own add_handler() since (somehow), all pending XDamageNotify events will not be correctly reported inside EvokeService handler. And about splash... splash will now keep it's window at the top, no matter what window is raised. This is a small hack until I implement _NET_WM_WINDOW_TYPE_SPLASH in edewm (I don't have to say that this hack works for all wm's I tested :P). Sound from splash is removed; reason for this is when evoke starts childs (only when X session was started), device descriptors will be used by childs too making sound device unusable and marked as busy. This can be solved by using better sound library, which is story for itself...
2008-01-14 15:50:30 +03:00
// EDEBUG(":) Opacity for %i = %i\n", win->id, p);
return p;
}
A lot of changes, especially the ways how screen is repainted (in composite). Composite will now draw only damaged regions, and their damage is (now) correctly reported, mostly due changes in main FLTK loop. Also there are two ways how evoke will be running: if USE_FLTK_LOOP_EMULATION is defined (default yes), it will fully emulate FLTK loop (as done before). Oposite way (without emulation) it will relay on FLTK message passing, but it is very unpredictable since FLTK will sometime miss SelectionClear events (XSETTINGS relay on it), probably due large XDamageNotify throttling. When emulation is used, there are no such problems since all events are processed before they are routed to FLTK. In composite is added another way of repainting (when USE_CHECK is defined), and it will relay on Fl::add_check() function; there are some differences between this function and timer used for screen refresh. Timer will try to refresh it every XX ms and when there are large number of XDamageNotify reports, this will not be suitable for movements smoothing on the screen; on other hand add_check() will call callback every time when event is processed, which brings smooth movements. For now only timer is used untill I finish compositing stuff. Also composite will handle messages from it's own add_handler() since (somehow), all pending XDamageNotify events will not be correctly reported inside EvokeService handler. And about splash... splash will now keep it's window at the top, no matter what window is raised. This is a small hack until I implement _NET_WM_WINDOW_TYPE_SPLASH in edewm (I don't have to say that this hack works for all wm's I tested :P). Sound from splash is removed; reason for this is when evoke starts childs (only when X session was started), device descriptors will be used by childs too making sound device unusable and marked as busy. This can be solved by using better sound library, which is story for itself...
2008-01-14 15:50:30 +03:00
//EDEBUG("Opacity for %i = %i\n", win->id, dflt);
return dflt;
}
double get_opacity_percent(CWindow* win, double dflt) {
unsigned int opacity = get_opacity_property(win, (unsigned int)(OPAQUE * dflt));
return opacity * 1.0 / OPAQUE;
}
Atom get_window_type_property(Window win) {
Atom actual;
int format;
unsigned long n, left;
unsigned char* data = NULL;
int ret = XGetWindowProperty(fl_display, win, _XA_NET_WM_WINDOW_TYPE, 0L, 1L, False,
XA_ATOM, &actual, &format, &n, &left, &data);
if(ret == Success && data != NULL) {
Atom a;
// TODO: replace memcpy call
memcpy(&a, data, sizeof(Atom));
XFree(data);
return a;
}
return _XA_NET_WM_WINDOW_TYPE_NORMAL;
}
Atom determine_window_type(Window win) {
Atom type = get_window_type_property(win);
if(type != _XA_NET_WM_WINDOW_TYPE_NORMAL)
return type;
// scan children
Window root_return, parent_return;
Window* children = NULL;
unsigned int nchildren;
A lot of changes, especially the ways how screen is repainted (in composite). Composite will now draw only damaged regions, and their damage is (now) correctly reported, mostly due changes in main FLTK loop. Also there are two ways how evoke will be running: if USE_FLTK_LOOP_EMULATION is defined (default yes), it will fully emulate FLTK loop (as done before). Oposite way (without emulation) it will relay on FLTK message passing, but it is very unpredictable since FLTK will sometime miss SelectionClear events (XSETTINGS relay on it), probably due large XDamageNotify throttling. When emulation is used, there are no such problems since all events are processed before they are routed to FLTK. In composite is added another way of repainting (when USE_CHECK is defined), and it will relay on Fl::add_check() function; there are some differences between this function and timer used for screen refresh. Timer will try to refresh it every XX ms and when there are large number of XDamageNotify reports, this will not be suitable for movements smoothing on the screen; on other hand add_check() will call callback every time when event is processed, which brings smooth movements. For now only timer is used untill I finish compositing stuff. Also composite will handle messages from it's own add_handler() since (somehow), all pending XDamageNotify events will not be correctly reported inside EvokeService handler. And about splash... splash will now keep it's window at the top, no matter what window is raised. This is a small hack until I implement _NET_WM_WINDOW_TYPE_SPLASH in edewm (I don't have to say that this hack works for all wm's I tested :P). Sound from splash is removed; reason for this is when evoke starts childs (only when X session was started), device descriptors will be used by childs too making sound device unusable and marked as busy. This can be solved by using better sound library, which is story for itself...
2008-01-14 15:50:30 +03:00
if(XQueryTree(fl_display, win, &root_return, &parent_return, &children, &nchildren) != 0) {
if(children)
XFree(children);
return _XA_NET_WM_WINDOW_TYPE_NORMAL;
}
for(unsigned int i = 0; i < nchildren; i++) {
type = determine_window_type(children[i]);
if(type != _XA_NET_WM_WINDOW_TYPE_NORMAL)
return type;
}
if(children)
XFree(children);
return _XA_NET_WM_WINDOW_TYPE_NORMAL;
}
void add_damage(XserverRegion damage) {
A lot of changes, especially the ways how screen is repainted (in composite). Composite will now draw only damaged regions, and their damage is (now) correctly reported, mostly due changes in main FLTK loop. Also there are two ways how evoke will be running: if USE_FLTK_LOOP_EMULATION is defined (default yes), it will fully emulate FLTK loop (as done before). Oposite way (without emulation) it will relay on FLTK message passing, but it is very unpredictable since FLTK will sometime miss SelectionClear events (XSETTINGS relay on it), probably due large XDamageNotify throttling. When emulation is used, there are no such problems since all events are processed before they are routed to FLTK. In composite is added another way of repainting (when USE_CHECK is defined), and it will relay on Fl::add_check() function; there are some differences between this function and timer used for screen refresh. Timer will try to refresh it every XX ms and when there are large number of XDamageNotify reports, this will not be suitable for movements smoothing on the screen; on other hand add_check() will call callback every time when event is processed, which brings smooth movements. For now only timer is used untill I finish compositing stuff. Also composite will handle messages from it's own add_handler() since (somehow), all pending XDamageNotify events will not be correctly reported inside EvokeService handler. And about splash... splash will now keep it's window at the top, no matter what window is raised. This is a small hack until I implement _NET_WM_WINDOW_TYPE_SPLASH in edewm (I don't have to say that this hack works for all wm's I tested :P). Sound from splash is removed; reason for this is when evoke starts childs (only when X session was started), device descriptors will be used by childs too making sound device unusable and marked as busy. This can be solved by using better sound library, which is story for itself...
2008-01-14 15:50:30 +03:00
if(allDamage != None) {
XFixesUnionRegion(fl_display, allDamage, allDamage, damage);
XFixesDestroyRegion(fl_display, damage);
} else
allDamage = damage;
}
void determine_mode(CWindow* win) {
if(win->picture_alpha) {
XRenderFreePicture(fl_display, win->picture_alpha);
win->picture_alpha = None;
}
if(win->picture_shadow) {
XRenderFreePicture(fl_display, win->picture_shadow);
win->picture_shadow = None;
}
XRenderPictFormat* format;
if(get_attributes_class_hack(&win->attr) == InputOnly)
format = 0;
else
format = XRenderFindVisualFormat(fl_display, win->attr.visual);
if(format && format->type == PictTypeDirect && format->direct.alphaMask)
win->mode = WIN_MODE_ARGB;
else if(win->opacity != OPAQUE)
win->mode = WIN_MODE_TRANS;
else
win->mode = WIN_MODE_SOLID;
if(win->extents) {
XserverRegion damage = XFixesCreateRegion(fl_display, 0, 0);
XFixesCopyRegion(fl_display, damage, win->extents);
add_damage(damage);
}
}
// TODO: make this a member
XserverRegion set_border_size(CWindow* win) {
/*
* if window doesn't exist anymore, this will generate an error
* as well as not generate a region. Perhaps a better XFixes
* architecture would be to have a request that copies instead
* of creates, that way you'd just end up with an empty region
* instead of an invalid XID.
*/
set_ignore(NextRequest(fl_display));
XserverRegion border = XFixesCreateRegionFromWindow(fl_display, win->id, WindowRegionBounding);
// translate this
set_ignore(NextRequest(fl_display));
XFixesTranslateRegion(fl_display, border,
win->attr.x + win->attr.border_width,
win->attr.y + win->attr.border_width);
return border;
}
// TODO: make this a part of paint_root()
Picture root_tile(void) {
Atom actual_type;
int actual_format;
unsigned long nitems;
unsigned long bytes_after;
unsigned char* prop;
Pixmap pixmap = None;
Atom pixmap_atom = XInternAtom(fl_display, "PIXMAP", False);
Window root = RootWindow(fl_display, fl_screen);
bool fill;
for(int i = 0; backgroundProps[i]; i++) {
if(XGetWindowProperty(fl_display, root, XInternAtom(fl_display, backgroundProps[i], False),
0, 4, False, AnyPropertyType,
&actual_type, &actual_format, &nitems, &bytes_after, &prop) == Success &&
actual_type == pixmap_atom &&
actual_format == 32 &&
nitems == 1) {
memcpy(&pixmap, prop, 4);
XFree(prop);
fill = false;
break;
}
}
if(!pixmap) {
pixmap = XCreatePixmap(fl_display, root, 1, 1, DefaultDepth(fl_display, fl_screen));
fill = true;
}
XRenderPictureAttributes pa;
pa.repeat = True;
Picture picture = XRenderCreatePicture(fl_display, pixmap,
XRenderFindVisualFormat(fl_display, DefaultVisual(fl_display, fl_screen)),
CPRepeat, &pa);
if(fill) {
XRenderColor c;
c.red = c.green = c.blue = 0x8080;
c.alpha = 0xffff;
XRenderFillRectangle(fl_display, PictOpSrc, picture, &c, 0, 0, 1, 1);
}
return picture;
}
Picture solid_picture(bool argb, double a, double r, double g, double b) {
Pixmap pixmap = XCreatePixmap(fl_display, RootWindow(fl_display, fl_screen), 1, 1, argb ? 32 : 8);
if(!pixmap)
return None;
XRenderPictureAttributes pa;
pa.repeat = True;
Picture picture = XRenderCreatePicture(fl_display, pixmap,
XRenderFindStandardFormat(fl_display, argb ? PictStandardARGB32 : PictStandardA8),
CPRepeat, &pa);
if(!picture) {
XFreePixmap(fl_display, pixmap);
return None;
}
XRenderColor color;
color.alpha = a * 0xffff;
color.red = r * 0xffff;
color.green = g * 0xffff;
color.blue = b * 0xffff;
XRenderFillRectangle(fl_display, PictOpSrc, picture, &color, 0, 0, 1, 1);
XFreePixmap(fl_display, pixmap);
return picture;
}
Composite::Composite() : manual_redirect(true) {
}
Composite::~Composite() {
EDEBUG("Composite::~Composite()\n");
A lot of changes, especially the ways how screen is repainted (in composite). Composite will now draw only damaged regions, and their damage is (now) correctly reported, mostly due changes in main FLTK loop. Also there are two ways how evoke will be running: if USE_FLTK_LOOP_EMULATION is defined (default yes), it will fully emulate FLTK loop (as done before). Oposite way (without emulation) it will relay on FLTK message passing, but it is very unpredictable since FLTK will sometime miss SelectionClear events (XSETTINGS relay on it), probably due large XDamageNotify throttling. When emulation is used, there are no such problems since all events are processed before they are routed to FLTK. In composite is added another way of repainting (when USE_CHECK is defined), and it will relay on Fl::add_check() function; there are some differences between this function and timer used for screen refresh. Timer will try to refresh it every XX ms and when there are large number of XDamageNotify reports, this will not be suitable for movements smoothing on the screen; on other hand add_check() will call callback every time when event is processed, which brings smooth movements. For now only timer is used untill I finish compositing stuff. Also composite will handle messages from it's own add_handler() since (somehow), all pending XDamageNotify events will not be correctly reported inside EvokeService handler. And about splash... splash will now keep it's window at the top, no matter what window is raised. This is a small hack until I implement _NET_WM_WINDOW_TYPE_SPLASH in edewm (I don't have to say that this hack works for all wm's I tested :P). Sound from splash is removed; reason for this is when evoke starts childs (only when X session was started), device descriptors will be used by childs too making sound device unusable and marked as busy. This can be solved by using better sound library, which is story for itself...
2008-01-14 15:50:30 +03:00
#ifdef USE_CHECK
Fl::remove_check(idle_cb);
#else
Fl::remove_timeout(idle_cb);
#endif
// TODO: this part should call finish_destroy_window()
CWindowListIter it = window_list.begin(), it_end = window_list.end();
while(it != it_end) {
delete *it;
++it;
}
}
bool Composite::init(void) {
another_is_running = false;
// set error handler first
XSetErrorHandler(xerror_handler);
int render_event;
if(!XRenderQueryExtension(fl_display, &render_event, &render_error)) {
EWARNING(ESTRLOC ": No render extension\n");
return false;
}
// check Composite extension
int composite_event, composite_error;
if(!XQueryExtension(fl_display, COMPOSITE_NAME, &composite_opcode, &composite_event, &composite_error)) {
EWARNING(ESTRLOC ": No composite extension\n");
return false;
}
int composite_major, composite_minor;
XCompositeQueryVersion(fl_display, &composite_major, &composite_minor);
EDEBUG(ESTRLOC ": Setting up XComposite version %i.%i\n", composite_major, composite_minor);
if(composite_major > 0 || composite_minor >= 2)
have_name_pixmap = true;
// check XDamage extension
if(!XDamageQueryExtension(fl_display, &damage_event, &damage_error)) {
EWARNING(ESTRLOC ": No damage extension\n");
return false;
}
// check XFixes extension
int xfixes_event;
if(!XFixesQueryExtension(fl_display, &xfixes_event, &xfixes_error)) {
EWARNING(ESTRLOC ": No XFixes extension\n");
return false;
}
_XA_NET_WM_WINDOW_OPACITY = XInternAtom(fl_display, "_NET_WM_WINDOW_OPACITY", False);
_XA_NET_WM_WINDOW_TYPE = XInternAtom(fl_display, "_NET_WM_WINDOW_TYPE", False);
_XA_NET_WM_WINDOW_TYPE_DESKTOP = XInternAtom(fl_display, "_NET_WM_WINDOW_TYPE_DESKTOP", False);
_XA_NET_WM_WINDOW_TYPE_DOCK = XInternAtom(fl_display, "_NET_WM_WINDOW_TYPE_DOCK", False);
_XA_NET_WM_WINDOW_TYPE_TOOLBAR = XInternAtom(fl_display, "_NET_WM_WINDOW_TYPE_TOOLBAR", False);
_XA_NET_WM_WINDOW_TYPE_MENU = XInternAtom(fl_display, "_NET_WM_WINDOW_TYPE_MENU", False);
_XA_NET_WM_WINDOW_TYPE_UTILITY = XInternAtom(fl_display, "_NET_WM_WINDOW_TYPE_UTILITY", False);
_XA_NET_WM_WINDOW_TYPE_SPLASH = XInternAtom(fl_display, "_NET_WM_WINDOW_TYPE_SPLASH", False);
_XA_NET_WM_WINDOW_TYPE_DIALOG = XInternAtom(fl_display, "_NET_WM_WINDOW_TYPE_DIALOG", False);
_XA_NET_WM_WINDOW_TYPE_NORMAL = XInternAtom(fl_display, "_NET_WM_WINDOW_TYPE_NORMAL", False);
allDamage = None;
clipChanged = true;
XRenderPictureAttributes pa;
pa.subwindow_mode = IncludeInferiors;
rootPicture = XRenderCreatePicture(fl_display, RootWindow(fl_display, fl_screen),
XRenderFindVisualFormat(fl_display, DefaultVisual(fl_display, fl_screen)), CPSubwindowMode, &pa);
blackPicture = solid_picture(true, 1, 0, 0, 0);
// now redirect all windows to the Composite
XGrabServer(fl_display);
/*
* If another manager is running, XCompositeRedirectSubwindows() will report it in xerror_handler().
* This only works if another-manager/evoke are both set in CompositeRedirectManual mode
*/
if(!manual_redirect)
XCompositeRedirectSubwindows(fl_display, RootWindow(fl_display, fl_screen), CompositeRedirectAutomatic);
else {
XCompositeRedirectSubwindows(fl_display, RootWindow(fl_display, fl_screen), CompositeRedirectManual);
#if 0
// Commented, since already selected in main evoke code (evoke.cpp).
XSelectInput(fl_display, RootWindow(fl_display, fl_screen),
SubstructureNotifyMask | ExposureMask | StructureNotifyMask | PropertyChangeMask);
#endif
Window root_ret, parent_ret;
Window* children;
unsigned int nchildren;
XQueryTree(fl_display, RootWindow(fl_display, fl_screen), &root_ret, &parent_ret, &children, &nchildren);
for(unsigned int i = 0; i < nchildren; i++)
add_window(children[i], i ? children[i-1] : None);
XFree(children);
}
XUngrabServer(fl_display);
/*
* draw all windows now, but only if we manualy manage them
* since window_list will be empty
*/
if(manual_redirect) {
A lot of changes, especially the ways how screen is repainted (in composite). Composite will now draw only damaged regions, and their damage is (now) correctly reported, mostly due changes in main FLTK loop. Also there are two ways how evoke will be running: if USE_FLTK_LOOP_EMULATION is defined (default yes), it will fully emulate FLTK loop (as done before). Oposite way (without emulation) it will relay on FLTK message passing, but it is very unpredictable since FLTK will sometime miss SelectionClear events (XSETTINGS relay on it), probably due large XDamageNotify throttling. When emulation is used, there are no such problems since all events are processed before they are routed to FLTK. In composite is added another way of repainting (when USE_CHECK is defined), and it will relay on Fl::add_check() function; there are some differences between this function and timer used for screen refresh. Timer will try to refresh it every XX ms and when there are large number of XDamageNotify reports, this will not be suitable for movements smoothing on the screen; on other hand add_check() will call callback every time when event is processed, which brings smooth movements. For now only timer is used untill I finish compositing stuff. Also composite will handle messages from it's own add_handler() since (somehow), all pending XDamageNotify events will not be correctly reported inside EvokeService handler. And about splash... splash will now keep it's window at the top, no matter what window is raised. This is a small hack until I implement _NET_WM_WINDOW_TYPE_SPLASH in edewm (I don't have to say that this hack works for all wm's I tested :P). Sound from splash is removed; reason for this is when evoke starts childs (only when X session was started), device descriptors will be used by childs too making sound device unusable and marked as busy. This can be solved by using better sound library, which is story for itself...
2008-01-14 15:50:30 +03:00
paint_all(None);
/*
* Using add_check() instead add_timeout() makes difference in redrawing
* since add_check() callback function will be called before FLTK flushes
* the display which makes it very suitable for smooth redrawing.
*
* On other hand, using add_timeout() will trigger timer each REFRESH_TIMEOUT
* no matter for pending events (especially XDamageNotifyEvent) and due that
* timeout we can miss some XDamage events, yielding little bit non-smooth redrawing.
*/
#ifdef USE_CHECK
Fl::add_check(idle_cb, this);
#else
Fl::add_timeout(REFRESH_TIMEOUT, idle_cb, this);
A lot of changes, especially the ways how screen is repainted (in composite). Composite will now draw only damaged regions, and their damage is (now) correctly reported, mostly due changes in main FLTK loop. Also there are two ways how evoke will be running: if USE_FLTK_LOOP_EMULATION is defined (default yes), it will fully emulate FLTK loop (as done before). Oposite way (without emulation) it will relay on FLTK message passing, but it is very unpredictable since FLTK will sometime miss SelectionClear events (XSETTINGS relay on it), probably due large XDamageNotify throttling. When emulation is used, there are no such problems since all events are processed before they are routed to FLTK. In composite is added another way of repainting (when USE_CHECK is defined), and it will relay on Fl::add_check() function; there are some differences between this function and timer used for screen refresh. Timer will try to refresh it every XX ms and when there are large number of XDamageNotify reports, this will not be suitable for movements smoothing on the screen; on other hand add_check() will call callback every time when event is processed, which brings smooth movements. For now only timer is used untill I finish compositing stuff. Also composite will handle messages from it's own add_handler() since (somehow), all pending XDamageNotify events will not be correctly reported inside EvokeService handler. And about splash... splash will now keep it's window at the top, no matter what window is raised. This is a small hack until I implement _NET_WM_WINDOW_TYPE_SPLASH in edewm (I don't have to say that this hack works for all wm's I tested :P). Sound from splash is removed; reason for this is when evoke starts childs (only when X session was started), device descriptors will be used by childs too making sound device unusable and marked as busy. This can be solved by using better sound library, which is story for itself...
2008-01-14 15:50:30 +03:00
#endif
}
return true;
}
void Composite::add_window(Window id, Window previous) {
CWindow* new_win = new CWindow;
new_win->id = id;
set_ignore(NextRequest(fl_display));
if(!XGetWindowAttributes(fl_display, id, &new_win->attr)) {
delete new_win;
return;
}
new_win->damaged = 0;
#if HAVE_NAME_WINDOW_PIXMAP
new_win->pixmap = None;
#endif
new_win->picture = None;
if(get_attributes_class_hack(&(new_win->attr)) == InputOnly) {
new_win->damage_sequence = 0;
new_win->damage = None;
} else {
new_win->damage_sequence = NextRequest(fl_display);
A lot of changes, especially the ways how screen is repainted (in composite). Composite will now draw only damaged regions, and their damage is (now) correctly reported, mostly due changes in main FLTK loop. Also there are two ways how evoke will be running: if USE_FLTK_LOOP_EMULATION is defined (default yes), it will fully emulate FLTK loop (as done before). Oposite way (without emulation) it will relay on FLTK message passing, but it is very unpredictable since FLTK will sometime miss SelectionClear events (XSETTINGS relay on it), probably due large XDamageNotify throttling. When emulation is used, there are no such problems since all events are processed before they are routed to FLTK. In composite is added another way of repainting (when USE_CHECK is defined), and it will relay on Fl::add_check() function; there are some differences between this function and timer used for screen refresh. Timer will try to refresh it every XX ms and when there are large number of XDamageNotify reports, this will not be suitable for movements smoothing on the screen; on other hand add_check() will call callback every time when event is processed, which brings smooth movements. For now only timer is used untill I finish compositing stuff. Also composite will handle messages from it's own add_handler() since (somehow), all pending XDamageNotify events will not be correctly reported inside EvokeService handler. And about splash... splash will now keep it's window at the top, no matter what window is raised. This is a small hack until I implement _NET_WM_WINDOW_TYPE_SPLASH in edewm (I don't have to say that this hack works for all wm's I tested :P). Sound from splash is removed; reason for this is when evoke starts childs (only when X session was started), device descriptors will be used by childs too making sound device unusable and marked as busy. This can be solved by using better sound library, which is story for itself...
2008-01-14 15:50:30 +03:00
new_win->damage = XDamageCreate(fl_display, new_win->id, XDamageReportNonEmpty);
}
new_win->picture_alpha = None;
new_win->picture_shadow = None;
new_win->border_size = None;
new_win->extents = None;
new_win->shadow = None;
A lot of changes, especially the ways how screen is repainted (in composite). Composite will now draw only damaged regions, and their damage is (now) correctly reported, mostly due changes in main FLTK loop. Also there are two ways how evoke will be running: if USE_FLTK_LOOP_EMULATION is defined (default yes), it will fully emulate FLTK loop (as done before). Oposite way (without emulation) it will relay on FLTK message passing, but it is very unpredictable since FLTK will sometime miss SelectionClear events (XSETTINGS relay on it), probably due large XDamageNotify throttling. When emulation is used, there are no such problems since all events are processed before they are routed to FLTK. In composite is added another way of repainting (when USE_CHECK is defined), and it will relay on Fl::add_check() function; there are some differences between this function and timer used for screen refresh. Timer will try to refresh it every XX ms and when there are large number of XDamageNotify reports, this will not be suitable for movements smoothing on the screen; on other hand add_check() will call callback every time when event is processed, which brings smooth movements. For now only timer is used untill I finish compositing stuff. Also composite will handle messages from it's own add_handler() since (somehow), all pending XDamageNotify events will not be correctly reported inside EvokeService handler. And about splash... splash will now keep it's window at the top, no matter what window is raised. This is a small hack until I implement _NET_WM_WINDOW_TYPE_SPLASH in edewm (I don't have to say that this hack works for all wm's I tested :P). Sound from splash is removed; reason for this is when evoke starts childs (only when X session was started), device descriptors will be used by childs too making sound device unusable and marked as busy. This can be solved by using better sound library, which is story for itself...
2008-01-14 15:50:30 +03:00
new_win->shadow_dx = 0;
new_win->shadow_dy = 0;
new_win->shadow_w = 0;
new_win->shadow_h = 0;
new_win->opacity = get_opacity_property(new_win, OPAQUE);
new_win->border_clip = None;
new_win->window_type = determine_window_type(new_win->id);
determine_mode(new_win);
// put window at the top
window_list.push_front(new_win);
// map it if was mapped before
if(new_win->attr.map_state == IsViewable)
map_window(new_win->id, new_win->damage_sequence - 1, true);
}
void Composite::map_window(Window id, unsigned long sequence, bool fade) {
CWindow* win = find_window(id);
if(!win)
return;
win->attr.map_state = IsViewable;
// this needs to be here or we loose transparency messages
A lot of changes, especially the ways how screen is repainted (in composite). Composite will now draw only damaged regions, and their damage is (now) correctly reported, mostly due changes in main FLTK loop. Also there are two ways how evoke will be running: if USE_FLTK_LOOP_EMULATION is defined (default yes), it will fully emulate FLTK loop (as done before). Oposite way (without emulation) it will relay on FLTK message passing, but it is very unpredictable since FLTK will sometime miss SelectionClear events (XSETTINGS relay on it), probably due large XDamageNotify throttling. When emulation is used, there are no such problems since all events are processed before they are routed to FLTK. In composite is added another way of repainting (when USE_CHECK is defined), and it will relay on Fl::add_check() function; there are some differences between this function and timer used for screen refresh. Timer will try to refresh it every XX ms and when there are large number of XDamageNotify reports, this will not be suitable for movements smoothing on the screen; on other hand add_check() will call callback every time when event is processed, which brings smooth movements. For now only timer is used untill I finish compositing stuff. Also composite will handle messages from it's own add_handler() since (somehow), all pending XDamageNotify events will not be correctly reported inside EvokeService handler. And about splash... splash will now keep it's window at the top, no matter what window is raised. This is a small hack until I implement _NET_WM_WINDOW_TYPE_SPLASH in edewm (I don't have to say that this hack works for all wm's I tested :P). Sound from splash is removed; reason for this is when evoke starts childs (only when X session was started), device descriptors will be used by childs too making sound device unusable and marked as busy. This can be solved by using better sound library, which is story for itself...
2008-01-14 15:50:30 +03:00
//XSelectInput(fl_display, win->id, PropertyChangeMask);
XSelectInput(fl_display, win->id, PropertyChangeMask | win->attr.your_event_mask | StructureNotifyMask);
win->damaged = 0;
/*
* XXX: a hack, not present in xcompmgr due main event
* loop changes
*/
A lot of changes, especially the ways how screen is repainted (in composite). Composite will now draw only damaged regions, and their damage is (now) correctly reported, mostly due changes in main FLTK loop. Also there are two ways how evoke will be running: if USE_FLTK_LOOP_EMULATION is defined (default yes), it will fully emulate FLTK loop (as done before). Oposite way (without emulation) it will relay on FLTK message passing, but it is very unpredictable since FLTK will sometime miss SelectionClear events (XSETTINGS relay on it), probably due large XDamageNotify throttling. When emulation is used, there are no such problems since all events are processed before they are routed to FLTK. In composite is added another way of repainting (when USE_CHECK is defined), and it will relay on Fl::add_check() function; there are some differences between this function and timer used for screen refresh. Timer will try to refresh it every XX ms and when there are large number of XDamageNotify reports, this will not be suitable for movements smoothing on the screen; on other hand add_check() will call callback every time when event is processed, which brings smooth movements. For now only timer is used untill I finish compositing stuff. Also composite will handle messages from it's own add_handler() since (somehow), all pending XDamageNotify events will not be correctly reported inside EvokeService handler. And about splash... splash will now keep it's window at the top, no matter what window is raised. This is a small hack until I implement _NET_WM_WINDOW_TYPE_SPLASH in edewm (I don't have to say that this hack works for all wm's I tested :P). Sound from splash is removed; reason for this is when evoke starts childs (only when X session was started), device descriptors will be used by childs too making sound device unusable and marked as busy. This can be solved by using better sound library, which is story for itself...
2008-01-14 15:50:30 +03:00
//repair_window(win);
// TODO: fading support
}
void Composite::unmap_window(Window id, bool fade) {
CWindow* win = find_window(id);
if(!win)
return;
win->attr.map_state = IsUnmapped;
#if HAVE_NAME_WINDOW_PIXMAP
if(win->pixmap && fade && fadeWindows) {
// TODO: fading support
} else
#endif
finish_unmap_window(win);
}
void Composite::finish_unmap_window(CWindow* win) {
win->damaged = 0;
if(win->extents != None) {
add_damage(win->extents); // destroy region
win->extents = None;
}
#if HAVE_NAME_WINDOW_PIXMAP
if(win->pixmap) {
XFreePixmap(fl_display, win->pixmap);
win->pixmap = None;
}
#endif
if(win->picture) {
set_ignore(NextRequest(fl_display));
XRenderFreePicture(fl_display, win->picture);
win->picture = None;
}
// don't care about properties anymore
set_ignore(NextRequest(fl_display));
XSelectInput(fl_display, win->id, 0);
if(win->border_size) {
set_ignore(NextRequest(fl_display));
XFixesDestroyRegion(fl_display, win->border_size);
win->border_size = None;
}
if(win->shadow) {
XRenderFreePicture(fl_display, win->shadow);
win->shadow = None;
}
if(win->border_clip) {
XFixesDestroyRegion(fl_display, win->border_clip);
win->border_clip = None;
}
clipChanged = true;
}
void Composite::configure_window(const XConfigureEvent* ce) {
CWindow* win = find_window(ce->window);
if(!win) {
if(ce->window == RootWindow(fl_display, fl_screen)) {
if(rootBuffer) {
XRenderFreePicture(fl_display, rootBuffer);
rootBuffer = None;
}
// TODO: here should be updated
// root_width and root_height
}
return;
}
XserverRegion damage = None;
damage = XFixesCreateRegion(fl_display, 0, 0);
if(win->extents != None)
XFixesCopyRegion(fl_display, damage, win->extents);
win->attr.x = ce->x;
win->attr.y = ce->y;
if(win->attr.width != ce->width || win->attr.height != ce->height) {
#if HAVE_NAME_WINDOW_PIXMAP
if(win->pixmap) {
XFreePixmap(fl_display, win->pixmap);
win->pixmap = None;
if(win->picture) {
XRenderFreePicture(fl_display, win->picture);
win->picture = None;
}
}
#endif
if(win->shadow) {
XRenderFreePicture(fl_display, win->shadow);
win->shadow = None;
}
}
win->attr.width = ce->width;
win->attr.height = ce->height;
win->attr.border_width = ce->border_width;
win->attr.override_redirect = ce->override_redirect;
#if 0
EDEBUG("--- before restack() ---\n");
CWindowListIter first = window_list.begin();
for(; first != window_list.end(); ++first)
EDEBUG("0x%x ", (*first)->id);
EDEBUG("\n");
EDEBUG("ME: 0x%x ABOVE: 0x%x\n", win->id, ce->above);
#endif
restack_window(win, ce->above);
#if 0
EDEBUG("--- after restack() ---\n");
first = window_list.begin();
for(; first != window_list.end(); ++first)
EDEBUG("0x%x ", (*first)->id);
EDEBUG("\n");
#endif
if(damage) {
XserverRegion extents = window_extents(win);
XFixesUnionRegion(fl_display, damage, damage, extents);
XFixesDestroyRegion(fl_display, extents);
add_damage(damage);
}
clipChanged = true;
}
void Composite::restack_window(CWindow* win, Window new_above) {
CWindowListIter it = window_list.begin(), it_end = window_list.end();
while(it != it_end) {
if(*it == win)
break;
++it;
}
Window old_above;
if(it == it_end) // not found
old_above = None;
else {
++it; // get the next one
A lot of changes, especially the ways how screen is repainted (in composite). Composite will now draw only damaged regions, and their damage is (now) correctly reported, mostly due changes in main FLTK loop. Also there are two ways how evoke will be running: if USE_FLTK_LOOP_EMULATION is defined (default yes), it will fully emulate FLTK loop (as done before). Oposite way (without emulation) it will relay on FLTK message passing, but it is very unpredictable since FLTK will sometime miss SelectionClear events (XSETTINGS relay on it), probably due large XDamageNotify throttling. When emulation is used, there are no such problems since all events are processed before they are routed to FLTK. In composite is added another way of repainting (when USE_CHECK is defined), and it will relay on Fl::add_check() function; there are some differences between this function and timer used for screen refresh. Timer will try to refresh it every XX ms and when there are large number of XDamageNotify reports, this will not be suitable for movements smoothing on the screen; on other hand add_check() will call callback every time when event is processed, which brings smooth movements. For now only timer is used untill I finish compositing stuff. Also composite will handle messages from it's own add_handler() since (somehow), all pending XDamageNotify events will not be correctly reported inside EvokeService handler. And about splash... splash will now keep it's window at the top, no matter what window is raised. This is a small hack until I implement _NET_WM_WINDOW_TYPE_SPLASH in edewm (I don't have to say that this hack works for all wm's I tested :P). Sound from splash is removed; reason for this is when evoke starts childs (only when X session was started), device descriptors will be used by childs too making sound device unusable and marked as busy. This can be solved by using better sound library, which is story for itself...
2008-01-14 15:50:30 +03:00
// check again
if(it == it_end)
old_above = None;
else
old_above = (*it)->id;
}
if(old_above != new_above) {
--it; // return to our window
EASSERT(*it == win && "Wrong code");
window_list.erase(it);
/*
it = window_list.begin();
it_end = window_list.end();
// find our window and remove it from current position
while(it != it_end) {
if(*it == win) {
window_list.erase(it);
break;
}
++it;
}*/
it = window_list.begin();
// now found new_above and insert our window
while(it != it_end) {
if((*it)->id == new_above) {
break;
}
++it;
}
// now insert where iterator was stopped (if not found 'new_above') it will insert at the end
window_list.insert(it, win);
}
}
void Composite::property_notify(const XPropertyEvent* pe) {
for(int i = 0; backgroundProps[i]; i++) {
if(pe->atom == XInternAtom(fl_display, backgroundProps[i], False)) {
if(rootTile) {
XClearArea(fl_display, RootWindow(fl_display, fl_screen), 0, 0, 0, 0, True);
XRenderFreePicture(fl_display, rootTile);
rootTile = None;
break;
}
}
}
// check if Trans property was changed
if(pe->atom == _XA_NET_WM_WINDOW_OPACITY) {
// reset mode and redraw window
CWindow* win = find_window(pe->window);
if(win) {
// TODO: fading support
win->opacity = get_opacity_property(win, OPAQUE);
determine_mode(win);
if(win->shadow) {
XRenderFreePicture(fl_display, win->shadow);
win->shadow = None;
win->extents = window_extents(win);
}
}
}
}
#if 0
static XRectangle* expose_rects = 0;
static int size_expose = 0;
static int n_expose = 0;
#endif
void Composite::expose_event(const XExposeEvent* ee) {
#if 0
if(ee->window != RootWindow(fl_display, fl_screen))
return;
int more = ee->count + 1;
if(n_expose == size_expose) {
if(expose_rects) {
expose_rects = (XRectangle*)realloc(expose_rects, (size_expose + more) * sizeof(XRectangle));
size_expose += more;
} else {
expose_rects = (XRectangle*)malloc(more * sizeof(XRectangle));
size_expose = more;
}
}
expose_rects[n_expose].x = ee->x;
expose_rects[n_expose].y = ee->y;
expose_rects[n_expose].width = ee->width;
expose_rects[n_expose].height = ee->height;
n_expose++;
if(ee->count == 0) {
// expose root
XserverRegion region = XFixesCreateRegion(fl_display, expose_rects, n_expose);
add_damage(region);
n_expose = 0;
}
#endif
XRectangle rect[1];
rect[0].x = ee->x;
rect[0].y = ee->y;
rect[0].width = ee->width;
rect[0].height = ee->height;
XserverRegion region = XFixesCreateRegion(fl_display, rect, 1);
add_damage(region);
}
void Composite::reparent_notify(const XReparentEvent* re) {
if(re->parent == RootWindow(fl_display, fl_screen))
add_window(re->window, 0);
else
destroy_window(re->window, false, true);
}
void Composite::circulate_window(const XCirculateEvent* ce) {
CWindow* win = find_window(ce->window);
if(!win)
return;
Window new_above;
if(ce->place == PlaceOnTop)
new_above = (*window_list.begin())->id;
else
new_above = None;
restack_window(win, new_above);
clipChanged = true;
}
CWindow* Composite::find_window(Window id) {
if(window_list.size() == 0)
return NULL;
CWindowListIter it = window_list.begin(), it_end = window_list.end();
while(it != it_end) {
if((*it)->id == id)
return *it;
++it;
}
return NULL;
}
XserverRegion Composite::window_extents(CWindow* win) {
XRectangle r;
r.x = win->attr.x;
r.y = win->attr.y;
r.width = win->attr.width + win->attr.border_width * 2;
r.height = win->attr.height + win->attr.border_width * 2;
if(!(win->window_type == _XA_NET_WM_WINDOW_TYPE_DOCK && excludeDockShadows)) {
// TODO: check this in xcompmgr since server shadows are not used, only client one
if(win->mode != WIN_MODE_ARGB) {
win->shadow_dx = shadowOffsetX;
win->shadow_dx = shadowOffsetX;
// make shadow if not already made
if(!win->shadow) {
double opacity = shadowOpacity;
if(win->mode == WIN_MODE_TRANS)
opacity = opacity * ((double)win->opacity)/((double)OPAQUE);
/*
win->shadow = shadow_picture(opacity, win->picture_alpha,
win->attr.width + win->attr.border_width * 2,
win->attr.height + win->attr.border_width * 2,
&win->shadow_w, &win->shadow_h);
*/
}
}
XRectangle sr;
sr.x = win->attr.x + win->shadow_dx;
sr.y = win->attr.y + win->shadow_dy;
sr.width = win->shadow_w;
sr.height = win->shadow_h;
if(sr.x < r.x) {
r.width = (r.x + r.width) - sr.x;
r.x = sr.x;
}
if(sr.y < r.y) {
r.height = (r.y + r.height) - sr.y;
r.y = sr.y;
}
if(sr.x + sr.width > r.x + r.width)
r.width = sr.x + sr.width - r.x;
if(sr.y + sr.height > r.y + r.height)
r.height = sr.y + sr.height - r.y;
}
return XFixesCreateRegion(fl_display, &r, 1);
}
void Composite::paint_root(void) {
if(!rootTile)
rootTile = root_tile();
XRenderComposite(fl_display, PictOpSrc, rootTile, None, rootBuffer, 0, 0, 0, 0, 0, 0,
DisplayWidth(fl_display, fl_screen),
DisplayHeight(fl_display, fl_screen));
}
void Composite::paint_all(XserverRegion region) {
//EDEBUG(ESTRLOC ": PAINT %i windows\n", window_list.size());
// if region is None repaint all screen
if(!region) {
XRectangle r;
r.x = 0;
r.y = 0;
// TODO: DisplayWidth/DisplayHeight should be calculated in init()
r.width = DisplayWidth(fl_display, fl_screen);
r.height = DisplayHeight(fl_display, fl_screen);
region = XFixesCreateRegion(fl_display, &r, 1);
}
if(!rootBuffer) {
Pixmap root_pix = XCreatePixmap(fl_display, RootWindow(fl_display, fl_screen),
DisplayWidth(fl_display, fl_screen),
DisplayHeight(fl_display, fl_screen),
DefaultDepth(fl_display, fl_screen));
rootBuffer = XRenderCreatePicture(fl_display, root_pix,
XRenderFindVisualFormat(fl_display, DefaultVisual(fl_display, fl_screen)), 0, 0);
XFreePixmap(fl_display, root_pix);
}
XFixesSetPictureClipRegion(fl_display, rootPicture, 0, 0, region);
// paint from top to bottom
CWindowListIter it = window_list.begin(), it_end = window_list.end();
for(; it != it_end; ++it) {
CWindow* win = *it;
// never painted, ignore it
if(!win->damaged)
continue;
// invisible, ignore it
if(win->attr.x + win->attr.width < 1 || win->attr.y + win->attr.height < 1
|| win->attr.x >= DisplayWidth(fl_display, fl_screen)
|| win->attr.y >= DisplayHeight(fl_display, fl_screen)) {
continue;
}
if(!win->picture) {
Drawable draw = win->id;
#ifdef HAVE_NAME_WINDOW_PIXMAP
if(hasNamePixmap && !win->pixmap)
win->pixmap = XCompositeNameWindowPixmap(fl_display, win->id);
if(win->pixmap)
draw = win->pixmap;
#endif
XRenderPictFormat* format = XRenderFindVisualFormat(fl_display, win->attr.visual);
A lot of changes, especially the ways how screen is repainted (in composite). Composite will now draw only damaged regions, and their damage is (now) correctly reported, mostly due changes in main FLTK loop. Also there are two ways how evoke will be running: if USE_FLTK_LOOP_EMULATION is defined (default yes), it will fully emulate FLTK loop (as done before). Oposite way (without emulation) it will relay on FLTK message passing, but it is very unpredictable since FLTK will sometime miss SelectionClear events (XSETTINGS relay on it), probably due large XDamageNotify throttling. When emulation is used, there are no such problems since all events are processed before they are routed to FLTK. In composite is added another way of repainting (when USE_CHECK is defined), and it will relay on Fl::add_check() function; there are some differences between this function and timer used for screen refresh. Timer will try to refresh it every XX ms and when there are large number of XDamageNotify reports, this will not be suitable for movements smoothing on the screen; on other hand add_check() will call callback every time when event is processed, which brings smooth movements. For now only timer is used untill I finish compositing stuff. Also composite will handle messages from it's own add_handler() since (somehow), all pending XDamageNotify events will not be correctly reported inside EvokeService handler. And about splash... splash will now keep it's window at the top, no matter what window is raised. This is a small hack until I implement _NET_WM_WINDOW_TYPE_SPLASH in edewm (I don't have to say that this hack works for all wm's I tested :P). Sound from splash is removed; reason for this is when evoke starts childs (only when X session was started), device descriptors will be used by childs too making sound device unusable and marked as busy. This can be solved by using better sound library, which is story for itself...
2008-01-14 15:50:30 +03:00
XRenderPictureAttributes pa;
pa.subwindow_mode = IncludeInferiors;
win->picture = XRenderCreatePicture(fl_display, draw, format, CPSubwindowMode, &pa);
}
if(clipChanged) {
if(win->border_size) {
set_ignore(NextRequest(fl_display));
XFixesDestroyRegion(fl_display, win->border_size);
win->border_size = None;
}
if(win->extents) {
XFixesDestroyRegion(fl_display, win->extents);
win->extents = None;
}
if(win->border_clip) {
XFixesDestroyRegion(fl_display, win->border_clip);
win->border_clip = None;
}
}
if(!win->border_size)
win->border_size = set_border_size(win);
if(!win->extents)
win->extents = window_extents(win);
// EDEBUG("mode :%i\n", win->mode);
if(win->mode == WIN_MODE_SOLID) {
int x, y, wid, hei;
#if HAVE_NAME_WINDOW_PIXMAP
x = win->attr.x;
y = win->attr.y;
wid = win->attr.width + win->attr.border_width * 2;
hei = win->attr.height + win->attr.border_width * 2;
#else
x = win->attr.x + win->attr.border_width;
y = win->attr.y + win->attr.border_width;
wid = win->attr.width;
hei = win->attr.height;
#endif
XFixesSetPictureClipRegion(fl_display, rootBuffer, 0, 0, region);
set_ignore(NextRequest(fl_display));
XFixesSubtractRegion(fl_display, region, region, win->border_size);
set_ignore(NextRequest(fl_display));
// EDEBUG(ESTRLOC ": Composite on %i x:%i y:%i w:%i h:%i\n", win->id, x, y, wid, hei);
XRenderComposite(fl_display, PictOpSrc, win->picture, None, rootBuffer,
0, 0, 0, 0, x, y, wid, hei);
}
if(!win->border_clip) {
win->border_clip = XFixesCreateRegion(fl_display, 0, 0);
XFixesCopyRegion(fl_display, win->border_clip, region);
}
}
XFixesSetPictureClipRegion(fl_display, rootBuffer, 0, 0, region);
paint_root();
/*
* paint from bottom to top
* use counter since checking only iterator will not pick up first element
*/
it = window_list.end();
it_end = window_list.begin();
--it; // decrease iterator so it pointing to the last element
for(unsigned int i = 0; i < window_list.size(); i++) {
CWindow* win = *it;
XFixesSetPictureClipRegion(fl_display, rootBuffer, 0, 0, win->border_clip);
// TODO: server shadows
// go and directly try to draw client shadows
// don't draw them on desktop
#if 0
if(win->shadow && win->window_type != _XA_NET_WM_WINDOW_TYPE_DESKTOP) {
XRenderComposite(fl_display, PictOpOver, blackPicture, win->shadow, rootBuffer,
0, 0, 0, 0,
win->attr.x + win->shadow_dx,
win->attr.y + win->shadow_dy,
win->shadow_w, win->shadow_h);
}
#endif
if(win->opacity != OPAQUE && !win->picture_alpha)
win->picture_alpha = solid_picture(false, (double)win->opacity / OPAQUE, 0, 0, 0);
// TODO: check this, xcompmgr have the same code for WIN_MODE_TRANS and WIN_MODE_ARGB
if(win->mode == WIN_MODE_TRANS || win->mode == WIN_MODE_ARGB) {
int x, y, wid, hei;
#if HAVE_NAME_WINDOW_PIXMAP
x = win->attr.x;
y = win->attr.y;
wid = win->attr.width + win->attr.border_width * 2;
hei = win->attr.height + win->attr.border_width * 2;
#else
x = win->attr.x + win->attr.border_width;
y = win->attr.y + win->attr.border_width;
wid = win->attr.width;
hei = win->attr.height;
#endif
set_ignore(NextRequest(fl_display));
A lot of changes, especially the ways how screen is repainted (in composite). Composite will now draw only damaged regions, and their damage is (now) correctly reported, mostly due changes in main FLTK loop. Also there are two ways how evoke will be running: if USE_FLTK_LOOP_EMULATION is defined (default yes), it will fully emulate FLTK loop (as done before). Oposite way (without emulation) it will relay on FLTK message passing, but it is very unpredictable since FLTK will sometime miss SelectionClear events (XSETTINGS relay on it), probably due large XDamageNotify throttling. When emulation is used, there are no such problems since all events are processed before they are routed to FLTK. In composite is added another way of repainting (when USE_CHECK is defined), and it will relay on Fl::add_check() function; there are some differences between this function and timer used for screen refresh. Timer will try to refresh it every XX ms and when there are large number of XDamageNotify reports, this will not be suitable for movements smoothing on the screen; on other hand add_check() will call callback every time when event is processed, which brings smooth movements. For now only timer is used untill I finish compositing stuff. Also composite will handle messages from it's own add_handler() since (somehow), all pending XDamageNotify events will not be correctly reported inside EvokeService handler. And about splash... splash will now keep it's window at the top, no matter what window is raised. This is a small hack until I implement _NET_WM_WINDOW_TYPE_SPLASH in edewm (I don't have to say that this hack works for all wm's I tested :P). Sound from splash is removed; reason for this is when evoke starts childs (only when X session was started), device descriptors will be used by childs too making sound device unusable and marked as busy. This can be solved by using better sound library, which is story for itself...
2008-01-14 15:50:30 +03:00
XRenderComposite(fl_display, PictOpOver, win->picture, win->picture_alpha, rootBuffer,
0, 0, 0, 0,
x, y, wid, hei);
A lot of changes, especially the ways how screen is repainted (in composite). Composite will now draw only damaged regions, and their damage is (now) correctly reported, mostly due changes in main FLTK loop. Also there are two ways how evoke will be running: if USE_FLTK_LOOP_EMULATION is defined (default yes), it will fully emulate FLTK loop (as done before). Oposite way (without emulation) it will relay on FLTK message passing, but it is very unpredictable since FLTK will sometime miss SelectionClear events (XSETTINGS relay on it), probably due large XDamageNotify throttling. When emulation is used, there are no such problems since all events are processed before they are routed to FLTK. In composite is added another way of repainting (when USE_CHECK is defined), and it will relay on Fl::add_check() function; there are some differences between this function and timer used for screen refresh. Timer will try to refresh it every XX ms and when there are large number of XDamageNotify reports, this will not be suitable for movements smoothing on the screen; on other hand add_check() will call callback every time when event is processed, which brings smooth movements. For now only timer is used untill I finish compositing stuff. Also composite will handle messages from it's own add_handler() since (somehow), all pending XDamageNotify events will not be correctly reported inside EvokeService handler. And about splash... splash will now keep it's window at the top, no matter what window is raised. This is a small hack until I implement _NET_WM_WINDOW_TYPE_SPLASH in edewm (I don't have to say that this hack works for all wm's I tested :P). Sound from splash is removed; reason for this is when evoke starts childs (only when X session was started), device descriptors will be used by childs too making sound device unusable and marked as busy. This can be solved by using better sound library, which is story for itself...
2008-01-14 15:50:30 +03:00
#if 0
A lot of changes, especially the ways how screen is repainted (in composite). Composite will now draw only damaged regions, and their damage is (now) correctly reported, mostly due changes in main FLTK loop. Also there are two ways how evoke will be running: if USE_FLTK_LOOP_EMULATION is defined (default yes), it will fully emulate FLTK loop (as done before). Oposite way (without emulation) it will relay on FLTK message passing, but it is very unpredictable since FLTK will sometime miss SelectionClear events (XSETTINGS relay on it), probably due large XDamageNotify throttling. When emulation is used, there are no such problems since all events are processed before they are routed to FLTK. In composite is added another way of repainting (when USE_CHECK is defined), and it will relay on Fl::add_check() function; there are some differences between this function and timer used for screen refresh. Timer will try to refresh it every XX ms and when there are large number of XDamageNotify reports, this will not be suitable for movements smoothing on the screen; on other hand add_check() will call callback every time when event is processed, which brings smooth movements. For now only timer is used untill I finish compositing stuff. Also composite will handle messages from it's own add_handler() since (somehow), all pending XDamageNotify events will not be correctly reported inside EvokeService handler. And about splash... splash will now keep it's window at the top, no matter what window is raised. This is a small hack until I implement _NET_WM_WINDOW_TYPE_SPLASH in edewm (I don't have to say that this hack works for all wm's I tested :P). Sound from splash is removed; reason for this is when evoke starts childs (only when X session was started), device descriptors will be used by childs too making sound device unusable and marked as busy. This can be solved by using better sound library, which is story for itself...
2008-01-14 15:50:30 +03:00
XRenderComposite(fl_display, PictOpOver, win->picture, win->picture_alpha, rootBuffer,
10, 0,
0, 0,
x+10, y, wid-10, 100);
// solid
XRenderComposite(fl_display, PictOpSrc, win->picture, None, rootBuffer,
10, 100,
0, 0,
x+10, y+100, wid-10, hei-100);
XRenderComposite(fl_display, PictOpSrc, win->picture, None, rootBuffer,
0, 0,
0, 0,
x, y, 10, hei);
#endif
A lot of changes, especially the ways how screen is repainted (in composite). Composite will now draw only damaged regions, and their damage is (now) correctly reported, mostly due changes in main FLTK loop. Also there are two ways how evoke will be running: if USE_FLTK_LOOP_EMULATION is defined (default yes), it will fully emulate FLTK loop (as done before). Oposite way (without emulation) it will relay on FLTK message passing, but it is very unpredictable since FLTK will sometime miss SelectionClear events (XSETTINGS relay on it), probably due large XDamageNotify throttling. When emulation is used, there are no such problems since all events are processed before they are routed to FLTK. In composite is added another way of repainting (when USE_CHECK is defined), and it will relay on Fl::add_check() function; there are some differences between this function and timer used for screen refresh. Timer will try to refresh it every XX ms and when there are large number of XDamageNotify reports, this will not be suitable for movements smoothing on the screen; on other hand add_check() will call callback every time when event is processed, which brings smooth movements. For now only timer is used untill I finish compositing stuff. Also composite will handle messages from it's own add_handler() since (somehow), all pending XDamageNotify events will not be correctly reported inside EvokeService handler. And about splash... splash will now keep it's window at the top, no matter what window is raised. This is a small hack until I implement _NET_WM_WINDOW_TYPE_SPLASH in edewm (I don't have to say that this hack works for all wm's I tested :P). Sound from splash is removed; reason for this is when evoke starts childs (only when X session was started), device descriptors will be used by childs too making sound device unusable and marked as busy. This can be solved by using better sound library, which is story for itself...
2008-01-14 15:50:30 +03:00
}
// XXX: a lot of errors here ?
if(win->border_clip != None) {
XFixesDestroyRegion(fl_display, win->border_clip);
win->border_clip = None;
}
// this will assure we catch first element too
if(it != it_end)
--it;
}
XFixesDestroyRegion(fl_display, region);
if(rootBuffer != rootPicture) {
XFixesSetPictureClipRegion(fl_display, rootBuffer, 0, 0, None);
XRenderComposite(fl_display, PictOpSrc, rootBuffer, None, rootPicture,
0, 0, 0, 0, 0, 0,
DisplayWidth(fl_display, fl_screen),
DisplayHeight(fl_display, fl_screen));
}
}
void Composite::damage_window(XDamageNotifyEvent* de) {
CWindow* win = find_window(de->drawable);
if(!win)
return;
A lot of changes, especially the ways how screen is repainted (in composite). Composite will now draw only damaged regions, and their damage is (now) correctly reported, mostly due changes in main FLTK loop. Also there are two ways how evoke will be running: if USE_FLTK_LOOP_EMULATION is defined (default yes), it will fully emulate FLTK loop (as done before). Oposite way (without emulation) it will relay on FLTK message passing, but it is very unpredictable since FLTK will sometime miss SelectionClear events (XSETTINGS relay on it), probably due large XDamageNotify throttling. When emulation is used, there are no such problems since all events are processed before they are routed to FLTK. In composite is added another way of repainting (when USE_CHECK is defined), and it will relay on Fl::add_check() function; there are some differences between this function and timer used for screen refresh. Timer will try to refresh it every XX ms and when there are large number of XDamageNotify reports, this will not be suitable for movements smoothing on the screen; on other hand add_check() will call callback every time when event is processed, which brings smooth movements. For now only timer is used untill I finish compositing stuff. Also composite will handle messages from it's own add_handler() since (somehow), all pending XDamageNotify events will not be correctly reported inside EvokeService handler. And about splash... splash will now keep it's window at the top, no matter what window is raised. This is a small hack until I implement _NET_WM_WINDOW_TYPE_SPLASH in edewm (I don't have to say that this hack works for all wm's I tested :P). Sound from splash is removed; reason for this is when evoke starts childs (only when X session was started), device descriptors will be used by childs too making sound device unusable and marked as busy. This can be solved by using better sound library, which is story for itself...
2008-01-14 15:50:30 +03:00
#if 0
// XXX: addon
while(XPending(fl_display)) {
XEvent ev;
if(XPeekEvent(fl_display, &ev) && ev.type == (damage_event + XDamageNotify) && ev.xany.window == win->id) {
XNextEvent(fl_display, &ev);
repair_window(win);
EDEBUG("XXXXXXXXXXXXX\n");
continue;
}
A lot of changes, especially the ways how screen is repainted (in composite). Composite will now draw only damaged regions, and their damage is (now) correctly reported, mostly due changes in main FLTK loop. Also there are two ways how evoke will be running: if USE_FLTK_LOOP_EMULATION is defined (default yes), it will fully emulate FLTK loop (as done before). Oposite way (without emulation) it will relay on FLTK message passing, but it is very unpredictable since FLTK will sometime miss SelectionClear events (XSETTINGS relay on it), probably due large XDamageNotify throttling. When emulation is used, there are no such problems since all events are processed before they are routed to FLTK. In composite is added another way of repainting (when USE_CHECK is defined), and it will relay on Fl::add_check() function; there are some differences between this function and timer used for screen refresh. Timer will try to refresh it every XX ms and when there are large number of XDamageNotify reports, this will not be suitable for movements smoothing on the screen; on other hand add_check() will call callback every time when event is processed, which brings smooth movements. For now only timer is used untill I finish compositing stuff. Also composite will handle messages from it's own add_handler() since (somehow), all pending XDamageNotify events will not be correctly reported inside EvokeService handler. And about splash... splash will now keep it's window at the top, no matter what window is raised. This is a small hack until I implement _NET_WM_WINDOW_TYPE_SPLASH in edewm (I don't have to say that this hack works for all wm's I tested :P). Sound from splash is removed; reason for this is when evoke starts childs (only when X session was started), device descriptors will be used by childs too making sound device unusable and marked as busy. This can be solved by using better sound library, which is story for itself...
2008-01-14 15:50:30 +03:00
break;
}
#endif
repair_window(win);
}
void Composite::repair_window(CWindow* win) {
XserverRegion parts;
if(!win->damaged) {
parts = window_extents(win);
set_ignore(NextRequest(fl_display));
XDamageSubtract(fl_display, win->damage, None, None);
} else {
parts = XFixesCreateRegion(fl_display, 0, 0);
set_ignore(NextRequest(fl_display));
XDamageSubtract(fl_display, win->damage, None, parts);
XFixesTranslateRegion(fl_display, parts,
win->attr.x + win->attr.border_width,
win->attr.y + win->attr.border_width);
// TODO: server shadows
}
if(parts == None)
EDEBUG("parts == None\n");
add_damage(parts);
win->damaged = 1;
}
void Composite::destroy_window(Window id, bool gone, bool fade) {
#if HAVE_NAME_WINDOW_PIXMAP
CWindow* win = find_window(id);
if(win && win->pixmap && fade && fadeWindows) {
// TODO: fading support
} else
#endif
finish_destroy_window(id, gone);
}
void Composite::finish_destroy_window(Window id, bool gone) {
CWindowListIter it = window_list.begin(), it_end = window_list.end();
while(it != it_end) {
if((*it)->id == id) {
CWindow* win = *it;
if(!gone)
finish_unmap_window(win);
if(win->picture) {
set_ignore(NextRequest(fl_display));
XRenderFreePicture(fl_display, win->picture);
win->picture = None;
}
if(win->picture_alpha) {
XRenderFreePicture(fl_display, win->picture_alpha);
win->picture_alpha = None;
}
if(win->picture_shadow) {
XRenderFreePicture(fl_display, win->picture_shadow);
win->picture_shadow = None;
}
if(win->damage != None) {
set_ignore(NextRequest(fl_display));
XDamageDestroy(fl_display, win->damage);
win->damage = None;
}
// TODO: fading support
window_list.erase(it);
delete win;
break;
}
++it;
}
}
A lot of changes, especially the ways how screen is repainted (in composite). Composite will now draw only damaged regions, and their damage is (now) correctly reported, mostly due changes in main FLTK loop. Also there are two ways how evoke will be running: if USE_FLTK_LOOP_EMULATION is defined (default yes), it will fully emulate FLTK loop (as done before). Oposite way (without emulation) it will relay on FLTK message passing, but it is very unpredictable since FLTK will sometime miss SelectionClear events (XSETTINGS relay on it), probably due large XDamageNotify throttling. When emulation is used, there are no such problems since all events are processed before they are routed to FLTK. In composite is added another way of repainting (when USE_CHECK is defined), and it will relay on Fl::add_check() function; there are some differences between this function and timer used for screen refresh. Timer will try to refresh it every XX ms and when there are large number of XDamageNotify reports, this will not be suitable for movements smoothing on the screen; on other hand add_check() will call callback every time when event is processed, which brings smooth movements. For now only timer is used untill I finish compositing stuff. Also composite will handle messages from it's own add_handler() since (somehow), all pending XDamageNotify events will not be correctly reported inside EvokeService handler. And about splash... splash will now keep it's window at the top, no matter what window is raised. This is a small hack until I implement _NET_WM_WINDOW_TYPE_SPLASH in edewm (I don't have to say that this hack works for all wm's I tested :P). Sound from splash is removed; reason for this is when evoke starts childs (only when X session was started), device descriptors will be used by childs too making sound device unusable and marked as busy. This can be solved by using better sound library, which is story for itself...
2008-01-14 15:50:30 +03:00
void Composite::update_screen(void) {
if(allDamage != None) {
paint_all(allDamage);
allDamage = None;
clipChanged = false;
}
}
int Composite::handle_xevents(const XEvent* xev) {
if(another_is_running || !manual_redirect)
A lot of changes, especially the ways how screen is repainted (in composite). Composite will now draw only damaged regions, and their damage is (now) correctly reported, mostly due changes in main FLTK loop. Also there are two ways how evoke will be running: if USE_FLTK_LOOP_EMULATION is defined (default yes), it will fully emulate FLTK loop (as done before). Oposite way (without emulation) it will relay on FLTK message passing, but it is very unpredictable since FLTK will sometime miss SelectionClear events (XSETTINGS relay on it), probably due large XDamageNotify throttling. When emulation is used, there are no such problems since all events are processed before they are routed to FLTK. In composite is added another way of repainting (when USE_CHECK is defined), and it will relay on Fl::add_check() function; there are some differences between this function and timer used for screen refresh. Timer will try to refresh it every XX ms and when there are large number of XDamageNotify reports, this will not be suitable for movements smoothing on the screen; on other hand add_check() will call callback every time when event is processed, which brings smooth movements. For now only timer is used untill I finish compositing stuff. Also composite will handle messages from it's own add_handler() since (somehow), all pending XDamageNotify events will not be correctly reported inside EvokeService handler. And about splash... splash will now keep it's window at the top, no matter what window is raised. This is a small hack until I implement _NET_WM_WINDOW_TYPE_SPLASH in edewm (I don't have to say that this hack works for all wm's I tested :P). Sound from splash is removed; reason for this is when evoke starts childs (only when X session was started), device descriptors will be used by childs too making sound device unusable and marked as busy. This can be solved by using better sound library, which is story for itself...
2008-01-14 15:50:30 +03:00
return 0;
switch(xev->type) {
case CreateNotify:
EDEBUG(ESTRLOC ": CreateNotify from composite\n");
add_window(xev->xcreatewindow.window, 0);
break;
case ConfigureNotify:
EDEBUG(ESTRLOC ": ConfigureNotify from composite\n");
configure_window(&xev->xconfigure);
break;
case DestroyNotify:
EDEBUG(ESTRLOC ": DestroyNotify from composite\n");
destroy_window(xev->xdestroywindow.window, true, true);
break;
case MapNotify:
EDEBUG(ESTRLOC ": MapNotify from composite\n");
map_window(xev->xmap.window, xev->xmap.serial, true);
break;
case UnmapNotify:
EDEBUG(ESTRLOC ": UnmapNotify from composite\n");
unmap_window(xev->xunmap.window, true);
break;
case ReparentNotify:
EDEBUG(ESTRLOC ": ReparentNotify from composite\n");
reparent_notify(&xev->xreparent);
break;
case CirculateNotify:
EDEBUG(ESTRLOC ": CirculateNotify from composite\n");
circulate_window(&xev->xcirculate);
break;
case Expose:
EDEBUG(ESTRLOC ": Expose from composite\n");
expose_event(&xev->xexpose);
break;
case PropertyNotify:
EDEBUG(ESTRLOC ": PropertyNotify from composite\n");
property_notify(&xev->xproperty);
break;
default:
A lot of changes, especially the ways how screen is repainted (in composite). Composite will now draw only damaged regions, and their damage is (now) correctly reported, mostly due changes in main FLTK loop. Also there are two ways how evoke will be running: if USE_FLTK_LOOP_EMULATION is defined (default yes), it will fully emulate FLTK loop (as done before). Oposite way (without emulation) it will relay on FLTK message passing, but it is very unpredictable since FLTK will sometime miss SelectionClear events (XSETTINGS relay on it), probably due large XDamageNotify throttling. When emulation is used, there are no such problems since all events are processed before they are routed to FLTK. In composite is added another way of repainting (when USE_CHECK is defined), and it will relay on Fl::add_check() function; there are some differences between this function and timer used for screen refresh. Timer will try to refresh it every XX ms and when there are large number of XDamageNotify reports, this will not be suitable for movements smoothing on the screen; on other hand add_check() will call callback every time when event is processed, which brings smooth movements. For now only timer is used untill I finish compositing stuff. Also composite will handle messages from it's own add_handler() since (somehow), all pending XDamageNotify events will not be correctly reported inside EvokeService handler. And about splash... splash will now keep it's window at the top, no matter what window is raised. This is a small hack until I implement _NET_WM_WINDOW_TYPE_SPLASH in edewm (I don't have to say that this hack works for all wm's I tested :P). Sound from splash is removed; reason for this is when evoke starts childs (only when X session was started), device descriptors will be used by childs too making sound device unusable and marked as busy. This can be solved by using better sound library, which is story for itself...
2008-01-14 15:50:30 +03:00
if(xev->type == (damage_event + XDamageNotify)) {
//EDEBUG("---------> %i <---------\n", damage_event + XDamageNotify);
damage_window((XDamageNotifyEvent*)xev);
A lot of changes, especially the ways how screen is repainted (in composite). Composite will now draw only damaged regions, and their damage is (now) correctly reported, mostly due changes in main FLTK loop. Also there are two ways how evoke will be running: if USE_FLTK_LOOP_EMULATION is defined (default yes), it will fully emulate FLTK loop (as done before). Oposite way (without emulation) it will relay on FLTK message passing, but it is very unpredictable since FLTK will sometime miss SelectionClear events (XSETTINGS relay on it), probably due large XDamageNotify throttling. When emulation is used, there are no such problems since all events are processed before they are routed to FLTK. In composite is added another way of repainting (when USE_CHECK is defined), and it will relay on Fl::add_check() function; there are some differences between this function and timer used for screen refresh. Timer will try to refresh it every XX ms and when there are large number of XDamageNotify reports, this will not be suitable for movements smoothing on the screen; on other hand add_check() will call callback every time when event is processed, which brings smooth movements. For now only timer is used untill I finish compositing stuff. Also composite will handle messages from it's own add_handler() since (somehow), all pending XDamageNotify events will not be correctly reported inside EvokeService handler. And about splash... splash will now keep it's window at the top, no matter what window is raised. This is a small hack until I implement _NET_WM_WINDOW_TYPE_SPLASH in edewm (I don't have to say that this hack works for all wm's I tested :P). Sound from splash is removed; reason for this is when evoke starts childs (only when X session was started), device descriptors will be used by childs too making sound device unusable and marked as busy. This can be solved by using better sound library, which is story for itself...
2008-01-14 15:50:30 +03:00
return 0;
}
break;
}
A lot of changes, especially the ways how screen is repainted (in composite). Composite will now draw only damaged regions, and their damage is (now) correctly reported, mostly due changes in main FLTK loop. Also there are two ways how evoke will be running: if USE_FLTK_LOOP_EMULATION is defined (default yes), it will fully emulate FLTK loop (as done before). Oposite way (without emulation) it will relay on FLTK message passing, but it is very unpredictable since FLTK will sometime miss SelectionClear events (XSETTINGS relay on it), probably due large XDamageNotify throttling. When emulation is used, there are no such problems since all events are processed before they are routed to FLTK. In composite is added another way of repainting (when USE_CHECK is defined), and it will relay on Fl::add_check() function; there are some differences between this function and timer used for screen refresh. Timer will try to refresh it every XX ms and when there are large number of XDamageNotify reports, this will not be suitable for movements smoothing on the screen; on other hand add_check() will call callback every time when event is processed, which brings smooth movements. For now only timer is used untill I finish compositing stuff. Also composite will handle messages from it's own add_handler() since (somehow), all pending XDamageNotify events will not be correctly reported inside EvokeService handler. And about splash... splash will now keep it's window at the top, no matter what window is raised. This is a small hack until I implement _NET_WM_WINDOW_TYPE_SPLASH in edewm (I don't have to say that this hack works for all wm's I tested :P). Sound from splash is removed; reason for this is when evoke starts childs (only when X session was started), device descriptors will be used by childs too making sound device unusable and marked as busy. This can be solved by using better sound library, which is story for itself...
2008-01-14 15:50:30 +03:00
return 1;
}