From 2424980f22456fe55520408a59198c645b9fe3ff Mon Sep 17 00:00:00 2001 From: Christopher Jeffrey Date: Wed, 8 Feb 2012 04:20:22 -0600 Subject: [PATCH 1/5] major refactor --- compton.c | 406 +++++++++++++++++++++++++++++++----------------------- 1 file changed, 234 insertions(+), 172 deletions(-) diff --git a/compton.c b/compton.c index a0d2b09..b309fef 100644 --- a/compton.c +++ b/compton.c @@ -2274,11 +2274,7 @@ main(int argc, char **argv) { unsigned int nchildren; int i; XRenderPictureAttributes pa; - XRectangle *expose_rects = 0; - int size_expose = 0; - int n_expose = 0; struct pollfd ufd; - int p; int composite_major, composite_minor; char *display = 0; int o; @@ -2290,9 +2286,6 @@ main(int argc, char **argv) { win_type_opacity[i] = 1.0; } - /* don't bother to draw a shadow for the desktop */ - win_type_shadow[WINTYPE_DESKTOP] = False; - while ((o = getopt(argc, argv, "D:I:O:d:r:o:m:l:t:i:e:scnfFCaSz")) != -1) { switch (o) { case 'd': @@ -2421,44 +2414,7 @@ main(int argc, char **argv) { } register_cm(scr); - - /* get atoms */ - extents_atom = XInternAtom(dpy, - "_NET_FRAME_EXTENTS", False); - opacity_atom = XInternAtom(dpy, - "_NET_WM_WINDOW_OPACITY", False); - - win_type_atom = XInternAtom(dpy, - "_NET_WM_WINDOW_TYPE", False); - win_type[WINTYPE_UNKNOWN] = 0; - win_type[WINTYPE_DESKTOP] = XInternAtom(dpy, - "_NET_WM_WINDOW_TYPE_DESKTOP", False); - win_type[WINTYPE_DOCK] = XInternAtom(dpy, - "_NET_WM_WINDOW_TYPE_DOCK", False); - win_type[WINTYPE_TOOLBAR] = XInternAtom(dpy, - "_NET_WM_WINDOW_TYPE_TOOLBAR", False); - win_type[WINTYPE_MENU] = XInternAtom(dpy, - "_NET_WM_WINDOW_TYPE_MENU", False); - win_type[WINTYPE_UTILITY] = XInternAtom(dpy, - "_NET_WM_WINDOW_TYPE_UTILITY", False); - win_type[WINTYPE_SPLASH] = XInternAtom(dpy, - "_NET_WM_WINDOW_TYPE_SPLASH", False); - win_type[WINTYPE_DIALOG] = XInternAtom(dpy, - "_NET_WM_WINDOW_TYPE_DIALOG", False); - win_type[WINTYPE_NORMAL] = XInternAtom(dpy, - "_NET_WM_WINDOW_TYPE_NORMAL", False); - win_type[WINTYPE_DROPDOWN_MENU] = XInternAtom(dpy, - "_NET_WM_WINDOW_TYPE_DROPDOWN_MENU", False); - win_type[WINTYPE_POPUP_MENU] = XInternAtom(dpy, - "_NET_WM_WINDOW_TYPE_POPUP_MENU", False); - win_type[WINTYPE_TOOLTIP] = XInternAtom(dpy, - "_NET_WM_WINDOW_TYPE_TOOLTIP", False); - win_type[WINTYPE_NOTIFY] = XInternAtom(dpy, - "_NET_WM_WINDOW_TYPE_NOTIFICATION", False); - win_type[WINTYPE_COMBO] = XInternAtom(dpy, - "_NET_WM_WINDOW_TYPE_COMBO", False); - win_type[WINTYPE_DND] = XInternAtom(dpy, - "_NET_WM_WINDOW_TYPE_DND", False); + get_atoms(); pa.subwindow_mode = IncludeInferiors; @@ -2514,134 +2470,8 @@ main(int argc, char **argv) { XNextEvent(dpy, &ev); - if ((ev.type & 0x7f) != KeymapNotify) { - discard_ignore(dpy, ev.xany.serial); - } + handle_event((XEvent *)&ev); -#if DEBUG_EVENTS - if (ev.type != damage_event + XDamageNotify) { - printf("event %10.10s serial 0x%08x window 0x%08x\n", - ev_name(&ev), ev_serial(&ev), ev_window(&ev)); - } -#endif - - switch (ev.type) { - case FocusIn: { - if (!inactive_opacity) break; - - win *fw = find_win(dpy, ev.xfocus.window); - if (IS_NORMAL_WIN(fw)) { - set_opacity(dpy, fw, OPAQUE); - } - break; - } - case FocusOut: { - if (!inactive_opacity) break; - - if (ev.xfocus.mode == NotifyGrab - || (ev.xfocus.mode == NotifyNormal - && (ev.xfocus.detail == NotifyNonlinear - || ev.xfocus.detail == NotifyNonlinearVirtual))) { - ; - } else { - break; - } - - win *fw = find_win(dpy, ev.xfocus.window); - if (IS_NORMAL_WIN(fw)) { - set_opacity(dpy, fw, INACTIVE_OPACITY); - } - break; - } - case CreateNotify: - add_win(dpy, ev.xcreatewindow.window, 0, - ev.xcreatewindow.override_redirect); - break; - case ConfigureNotify: - configure_win(dpy, &ev.xconfigure); - break; - case DestroyNotify: - destroy_win(dpy, ev.xdestroywindow.window, True); - break; - case MapNotify: - map_win(dpy, ev.xmap.window, ev.xmap.serial, True, - ev.xmap.override_redirect); - break; - case UnmapNotify: - unmap_win(dpy, ev.xunmap.window, True); - break; - case ReparentNotify: - if (ev.xreparent.parent == root) { - add_win(dpy, ev.xreparent.window, 0, - ev.xreparent.override_redirect); - } else { - destroy_win(dpy, ev.xreparent.window, True); - } - break; - case CirculateNotify: - circulate_win(dpy, &ev.xcirculate); - break; - case Expose: - if (ev.xexpose.window == root) { - int more = ev.xexpose.count + 1; - if (n_expose == size_expose) { - if (expose_rects) { - expose_rects = realloc(expose_rects, - (size_expose + more) * sizeof(XRectangle)); - size_expose += more; - } else { - expose_rects = malloc(more * sizeof(XRectangle)); - size_expose = more; - } - } - expose_rects[n_expose].x = ev.xexpose.x; - expose_rects[n_expose].y = ev.xexpose.y; - expose_rects[n_expose].width = ev.xexpose.width; - expose_rects[n_expose].height = ev.xexpose.height; - n_expose++; - if (ev.xexpose.count == 0) { - expose_root(dpy, root, expose_rects, n_expose); - n_expose = 0; - } - } - break; - case PropertyNotify: - for (p = 0; background_props[p]; p++) { - if (ev.xproperty.atom == - XInternAtom(dpy, background_props[p], False)) { - if (root_tile) { - XClearArea(dpy, root, 0, 0, 0, 0, True); - XRenderFreePicture(dpy, root_tile); - root_tile = None; - break; - } - } - } - /* check if Trans property was changed */ - if (ev.xproperty.atom == opacity_atom) { - /* reset mode and redraw window */ - win *w = find_win(dpy, ev.xproperty.window); - if (w) { - double def = win_type_opacity[w->window_type]; - set_opacity(dpy, w, - get_opacity_prop(dpy, w, (unsigned long)(OPAQUE * def))); - } - } - if (frame_opacity && ev.xproperty.atom == extents_atom) { - win *w = find_toplevel(dpy, ev.xproperty.window); - if (w) { - get_frame_extents(dpy, w->client_win, - &w->left_width, &w->right_width, - &w->top_width, &w->bottom_width); - } - } - break; - default: - if (ev.type == damage_event + XDamageNotify) { - damage_win(dpy, (XDamageNotifyEvent *)&ev); - } - break; - } } while (QLength(dpy)); if (all_damage) { @@ -2654,3 +2484,235 @@ main(int argc, char **argv) { } } } + +static void +get_atoms() { + extents_atom = XInternAtom(dpy, + "_NET_FRAME_EXTENTS", False); + opacity_atom = XInternAtom(dpy, + "_NET_WM_WINDOW_OPACITY", False); + + win_type_atom = XInternAtom(dpy, + "_NET_WM_WINDOW_TYPE", False); + win_type[WINTYPE_UNKNOWN] = 0; + win_type[WINTYPE_DESKTOP] = XInternAtom(dpy, + "_NET_WM_WINDOW_TYPE_DESKTOP", False); + win_type[WINTYPE_DOCK] = XInternAtom(dpy, + "_NET_WM_WINDOW_TYPE_DOCK", False); + win_type[WINTYPE_TOOLBAR] = XInternAtom(dpy, + "_NET_WM_WINDOW_TYPE_TOOLBAR", False); + win_type[WINTYPE_MENU] = XInternAtom(dpy, + "_NET_WM_WINDOW_TYPE_MENU", False); + win_type[WINTYPE_UTILITY] = XInternAtom(dpy, + "_NET_WM_WINDOW_TYPE_UTILITY", False); + win_type[WINTYPE_SPLASH] = XInternAtom(dpy, + "_NET_WM_WINDOW_TYPE_SPLASH", False); + win_type[WINTYPE_DIALOG] = XInternAtom(dpy, + "_NET_WM_WINDOW_TYPE_DIALOG", False); + win_type[WINTYPE_NORMAL] = XInternAtom(dpy, + "_NET_WM_WINDOW_TYPE_NORMAL", False); + win_type[WINTYPE_DROPDOWN_MENU] = XInternAtom(dpy, + "_NET_WM_WINDOW_TYPE_DROPDOWN_MENU", False); + win_type[WINTYPE_POPUP_MENU] = XInternAtom(dpy, + "_NET_WM_WINDOW_TYPE_POPUP_MENU", False); + win_type[WINTYPE_TOOLTIP] = XInternAtom(dpy, + "_NET_WM_WINDOW_TYPE_TOOLTIP", False); + win_type[WINTYPE_NOTIFY] = XInternAtom(dpy, + "_NET_WM_WINDOW_TYPE_NOTIFICATION", False); + win_type[WINTYPE_COMBO] = XInternAtom(dpy, + "_NET_WM_WINDOW_TYPE_COMBO", False); + win_type[WINTYPE_DND] = XInternAtom(dpy, + "_NET_WM_WINDOW_TYPE_DND", False); +} + +inline static void +ev_focus_in(XFocusChangeEvent *ev) { + if (!inactive_opacity) return; + + win *fw = find_win(dpy, ev->window); + if (IS_NORMAL_WIN(fw)) { + set_opacity(dpy, fw, OPAQUE); + } +} + +inline static void +ev_focus_out(XFocusChangeEvent *ev) { + if (!inactive_opacity) return; + + if (ev->mode == NotifyGrab + || (ev->mode == NotifyNormal + && (ev->detail == NotifyNonlinear + || ev->detail == NotifyNonlinearVirtual))) { + ; + } else { + return; + } + + win *fw = find_win(dpy, ev->window); + if (IS_NORMAL_WIN(fw)) { + set_opacity(dpy, fw, INACTIVE_OPACITY); + } +} + +inline static void +ev_create_notify(XCreateWindowEvent *ev) { + add_win(dpy, ev->window, 0, ev->override_redirect); +} + +inline static void +ev_configure_notify(XConfigureEvent *ev) { + configure_win(dpy, ev); +} + +inline static void +ev_destroy_notify(XDestroyWindowEvent *ev) { + destroy_win(dpy, ev->window, True); +} + +inline static void +ev_map_notify(XMapEvent *ev) { + map_win(dpy, ev->window, ev->serial, True, ev->override_redirect); +} + +inline static void +ev_unmap_notify(XUnmapEvent *ev) { + unmap_win(dpy, ev->window, True); +} + +inline static void +ev_reparent_notify(XReparentEvent *ev) { + if (ev->parent == root) { + add_win(dpy, ev->window, 0, ev->override_redirect); + } else { + destroy_win(dpy, ev->window, True); + } +} + +inline static void +ev_circulate_notify(XCirculateEvent *ev) { + circulate_win(dpy, ev); +} + +inline static void +ev_expose(XExposeEvent *ev) { + if (ev->window == root) { + int more = ev->count + 1; + if (n_expose == size_expose) { + if (expose_rects) { + expose_rects = realloc(expose_rects, + (size_expose + more) * sizeof(XRectangle)); + size_expose += more; + } else { + expose_rects = malloc(more * sizeof(XRectangle)); + size_expose = more; + } + } + + expose_rects[n_expose].x = ev->x; + expose_rects[n_expose].y = ev->y; + expose_rects[n_expose].width = ev->width; + expose_rects[n_expose].height = ev->height; + n_expose++; + + if (ev->count == 0) { + expose_root(dpy, root, expose_rects, n_expose); + n_expose = 0; + } + } +} + +inline static void +ev_property_notify(XPropertyEvent *ev) { + int p; + for (p = 0; background_props[p]; p++) { + if (ev->atom == XInternAtom(dpy, background_props[p], False)) { + if (root_tile) { + XClearArea(dpy, root, 0, 0, 0, 0, True); + XRenderFreePicture(dpy, root_tile); + root_tile = None; + break; + } + } + } + + /* check if Trans property was changed */ + if (ev->atom == opacity_atom) { + /* reset mode and redraw window */ + win *w = find_win(dpy, ev->window); + if (w) { + double def = win_type_opacity[w->window_type]; + set_opacity(dpy, w, + get_opacity_prop(dpy, w, (unsigned long)(OPAQUE * def))); + } + } + + if (frame_opacity && ev->atom == extents_atom) { + win *w = find_toplevel(dpy, ev->window); + if (w) { + get_frame_extents(dpy, w->client_win, + &w->left_width, &w->right_width, + &w->top_width, &w->bottom_width); + } + } +} + +inline static void +ev_damage_notify(XDamageNotifyEvent *ev) { + damage_win(dpy, ev); +} + +inline static void +handle_event(XEvent *ev) { + if ((ev->type & 0x7f) != KeymapNotify) { + discard_ignore(dpy, ev->xany.serial); + } + +#if DEBUG_EVENTS + if (ev->type != damage_event + XDamageNotify) { + printf("event %10.10s serial 0x%08x window 0x%08x\n", + ev_name(ev), ev_serial(ev), ev_window(ev)); + } +#endif + + switch (ev->type) { + case FocusIn: + ev_focus_in((XFocusChangeEvent *)ev); + break; + case FocusOut: + ev_focus_out((XFocusChangeEvent *)ev); + break; + case CreateNotify: + ev_create_notify((XCreateWindowEvent *)ev); + break; + case ConfigureNotify: + ev_configure_notify((XConfigureEvent *)ev); + break; + case DestroyNotify: + ev_destroy_notify((XDestroyWindowEvent *)ev); + break; + case MapNotify: + ev_map_notify((XMapEvent *)ev); + break; + case UnmapNotify: + ev_unmap_notify((XUnmapEvent *)ev); + break; + case ReparentNotify: + ev_reparent_notify((XReparentEvent *)ev); + break; + case CirculateNotify: + ev_circulate_notify((XCirculateEvent *)ev); + break; + case Expose: + ev_expose((XExposeEvent *)ev); + break; + case PropertyNotify: + ev_property_notify((XPropertyEvent *)ev); + break; + default: + if (ev->type == damage_event + XDamageNotify) { + ev_damage_notify((XDamageNotifyEvent *)ev); + } + break; + } +} + From cfe78e7ca5e76924a852bd5da808be0abc140658 Mon Sep 17 00:00:00 2001 From: Christopher Jeffrey Date: Wed, 8 Feb 2012 04:31:39 -0600 Subject: [PATCH 2/5] put all functions in header file --- compton.c | 21 +--- compton.h | 345 ++++++++++++++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 351 insertions(+), 15 deletions(-) diff --git a/compton.c b/compton.c index b309fef..944a304 100644 --- a/compton.c +++ b/compton.c @@ -113,6 +113,8 @@ typedef struct _fade { Display *dpy; } fade; +#include "compton.h" + win *list; fade *fades; Display *dpy; @@ -159,15 +161,6 @@ conv *gaussian_map; #define DEBUG_EVENTS 0 #define MONITOR_REPAINT 0 -static void -determine_mode(Display *dpy, win *w); - -static double -get_opacity_percent(Display *dpy, win *w); - -static XserverRegion -win_extents(Display *dpy, win *w); - int shadow_radius = 12; int shadow_offset_x = -15; int shadow_offset_y = -15; @@ -1452,12 +1445,6 @@ determine_wintype(Display *dpy, Window w, Window top) { } } -static unsigned int -get_opacity_prop(Display *dpy, win *w, unsigned int def); - -static void -configure_win(Display *dpy, XConfigureEvent *ce); - static void map_win(Display *dpy, Window id, unsigned long sequence, Bool fade, @@ -2593,6 +2580,10 @@ ev_circulate_notify(XCirculateEvent *ev) { circulate_win(dpy, ev); } +XRectangle *expose_rects = 0; +int size_expose = 0; +int n_expose = 0; + inline static void ev_expose(XExposeEvent *ev) { if (ev->window == root) { diff --git a/compton.h b/compton.h index 8b13789..8d3a2cb 100644 --- a/compton.h +++ b/compton.h @@ -1 +1,346 @@ +#if 0 +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include +#include +#include + +#if COMPOSITE_MAJOR > 0 || COMPOSITE_MINOR >= 2 +#define HAS_NAME_WINDOW_PIXMAP 1 +#endif + +#define CAN_DO_USABLE 0 +#define DEBUG_REPAINT 0 +#define DEBUG_EVENTS 0 +#define MONITOR_REPAINT 0 + +#define OPAQUE 0xffffffff + +typedef enum { + WINTYPE_UNKNOWN, + WINTYPE_DESKTOP, + WINTYPE_DOCK, + WINTYPE_TOOLBAR, + WINTYPE_MENU, + WINTYPE_UTILITY, + WINTYPE_SPLASH, + WINTYPE_DIALOG, + WINTYPE_NORMAL, + WINTYPE_DROPDOWN_MENU, + WINTYPE_POPUP_MENU, + WINTYPE_TOOLTIP, + WINTYPE_NOTIFY, + WINTYPE_COMBO, + WINTYPE_DND, + NUM_WINTYPES +} wintype; + +typedef struct _ignore { + struct _ignore *next; + unsigned long sequence; +} ignore; + +typedef struct _win { + struct _win *next; + Window id; + Window client_win; +#if HAS_NAME_WINDOW_PIXMAP + Pixmap pixmap; +#endif + XWindowAttributes a; +#if CAN_DO_USABLE + Bool usable; /* mapped and all damaged at one point */ + XRectangle damage_bounds; /* bounds of damage */ +#endif + int mode; + int damaged; + Damage damage; + Picture picture; + Picture alpha_pict; + Picture alpha_border_pict; + Picture shadow_pict; + XserverRegion border_size; + XserverRegion extents; + Picture shadow; + int shadow_dx; + int shadow_dy; + int shadow_width; + int shadow_height; + unsigned int opacity; + wintype window_type; + unsigned long damage_sequence; /* sequence when damage was created */ + Bool destroyed; + unsigned int left_width; + unsigned int right_width; + unsigned int top_width; + unsigned int bottom_width; + + Bool need_configure; + XConfigureEvent queue_configure; + + /* for drawing translucent windows */ + XserverRegion border_clip; + struct _win *prev_trans; +} win; + +typedef struct _conv { + int size; + double *data; +} conv; + +typedef struct _fade { + struct _fade *next; + win *w; + double cur; + double finish; + double step; + void (*callback) (Display *dpy, win *w); + Display *dpy; +} fade; +#endif + +int +get_time_in_milliseconds(); + +fade * +find_fade(win *w); + +void +dequeue_fade(Display *dpy, fade *f); + +void +cleanup_fade(Display *dpy, win *w); + +void +enqueue_fade(Display *dpy, fade *f); + +static void +set_fade(Display *dpy, win *w, double start, + double finish, double step, + void(*callback) (Display *dpy, win *w), + Bool exec_callback, Bool override); + +int +fade_timeout(void); + +void +run_fades(Display *dpy); + +static double +gaussian(double r, double x, double y); + +static conv * +make_gaussian_map(Display *dpy, double r); + +static unsigned char +sum_gaussian(conv *map, double opacity, + int x, int y, int width, int height); + +static void +presum_gaussian(conv *map); + +static XImage * +make_shadow(Display *dpy, double opacity, + int width, int height); + +static Picture +shadow_picture(Display *dpy, double opacity, Picture alpha_pict, + int width, int height, int *wp, int *hp); + +Picture +solid_picture(Display *dpy, Bool argb, double a, + double r, double g, double b); + +void +discard_ignore(Display *dpy, unsigned long sequence); + +void +set_ignore(Display *dpy, unsigned long sequence); + +int +should_ignore(Display *dpy, unsigned long sequence); + +static win * +find_win(Display *dpy, Window id); + +static win * +find_toplevel(Display *dpy, Window id); + +static Picture +root_tile_f(Display *dpy); + +static void +paint_root(Display *dpy); + +static XserverRegion +win_extents(Display *dpy, win *w); + +static XserverRegion +border_size(Display *dpy, win *w); + +static Window +find_client_win(Display *dpy, Window win); + +static void +get_frame_extents(Display *dpy, Window w, + unsigned int *left, + unsigned int *right, + unsigned int *top, + unsigned int *bottom); + +static void +paint_all(Display *dpy, XserverRegion region); + +static void +add_damage(Display *dpy, XserverRegion damage); + +static void +repair_win(Display *dpy, win *w); + +#if 0 +static const char* +wintype_name(wintype type); +#endif + +static wintype +get_wintype_prop(Display * dpy, Window w); + +static wintype +determine_wintype(Display *dpy, Window w, Window top); + +static void +map_win(Display *dpy, Window id, + unsigned long sequence, Bool fade, + Bool override_redirect); + +static void +finish_unmap_win(Display *dpy, win *w); + +#if HAS_NAME_WINDOW_PIXMAP +static void +unmap_callback(Display *dpy, win *w); +#endif + +static void +unmap_win(Display *dpy, Window id, Bool fade); + +static unsigned int +get_opacity_prop(Display *dpy, win *w, unsigned int def); + +static double +get_opacity_percent(Display *dpy, win *w); + +static void +determine_mode(Display *dpy, win *w); + +static void +set_opacity(Display *dpy, win *w, unsigned long opacity); + +static void +add_win(Display *dpy, Window id, Window prev, Bool override_redirect); + +void +restack_win(Display *dpy, win *w, Window new_above); + +static void +configure_win(Display *dpy, XConfigureEvent *ce); + +static void +circulate_win(Display *dpy, XCirculateEvent *ce); + +static void +finish_destroy_win(Display *dpy, Window id); + +#if HAS_NAME_WINDOW_PIXMAP +static void +destroy_callback(Display *dpy, win *w); +#endif + +static void +destroy_win(Display *dpy, Window id, Bool fade); + +#if 0 +static void +dump_win(win *w); +#endif + +static void +damage_win(Display *dpy, XDamageNotifyEvent *de); + +static int +error(Display *dpy, XErrorEvent *ev); + +static void +expose_root(Display *dpy, Window root, XRectangle *rects, int nrects); + +#if DEBUG_EVENTS +static int +ev_serial(XEvent *ev); + +static char * +ev_name(XEvent *ev); + +static Window +ev_window(XEvent *ev); +#endif + +void +usage(char *program); + +static void +register_cm(int scr); + +inline static void +ev_focus_in(XFocusChangeEvent *ev); + +inline static void +ev_focus_out(XFocusChangeEvent *ev); + +inline static void +ev_create_notify(XCreateWindowEvent *ev); + +inline static void +ev_configure_notify(XConfigureEvent *ev); + +inline static void +ev_destroy_notify(XDestroyWindowEvent *ev); + +inline static void +ev_map_notify(XMapEvent *ev); + +inline static void +ev_unmap_notify(XUnmapEvent *ev); + +inline static void +ev_reparent_notify(XReparentEvent *ev); + +inline static void +ev_circulate_notify(XCirculateEvent *ev); + +inline static void +ev_expose(XExposeEvent *ev); + +inline static void +ev_property_notify(XPropertyEvent *ev); + +inline static void +ev_damage_notify(XDamageNotifyEvent *ev); + +inline static void +handle_event(XEvent *ev); + +static void +get_atoms(); + From eee566860084297841a93664cfc2f48cc84cd3e6 Mon Sep 17 00:00:00 2001 From: Christopher Jeffrey Date: Wed, 8 Feb 2012 04:34:33 -0600 Subject: [PATCH 3/5] put typedefs and defs in header --- compton.c | 111 ------------------------------------------------------ compton.h | 2 - 2 files changed, 113 deletions(-) diff --git a/compton.c b/compton.c index 944a304..c1c3a0b 100644 --- a/compton.c +++ b/compton.c @@ -8,111 +8,6 @@ * */ -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#include -#include -#include -#include -#include -#include - -#if COMPOSITE_MAJOR > 0 || COMPOSITE_MINOR >= 2 -#define HAS_NAME_WINDOW_PIXMAP 1 -#endif - -#define CAN_DO_USABLE 0 - -typedef enum { - WINTYPE_UNKNOWN, - WINTYPE_DESKTOP, - WINTYPE_DOCK, - WINTYPE_TOOLBAR, - WINTYPE_MENU, - WINTYPE_UTILITY, - WINTYPE_SPLASH, - WINTYPE_DIALOG, - WINTYPE_NORMAL, - WINTYPE_DROPDOWN_MENU, - WINTYPE_POPUP_MENU, - WINTYPE_TOOLTIP, - WINTYPE_NOTIFY, - WINTYPE_COMBO, - WINTYPE_DND, - NUM_WINTYPES -} wintype; - -typedef struct _ignore { - struct _ignore *next; - unsigned long sequence; -} ignore; - -typedef struct _win { - struct _win *next; - Window id; - Window client_win; -#if HAS_NAME_WINDOW_PIXMAP - Pixmap pixmap; -#endif - XWindowAttributes a; -#if CAN_DO_USABLE - Bool usable; /* mapped and all damaged at one point */ - XRectangle damage_bounds; /* bounds of damage */ -#endif - int mode; - int damaged; - Damage damage; - Picture picture; - Picture alpha_pict; - Picture alpha_border_pict; - Picture shadow_pict; - XserverRegion border_size; - XserverRegion extents; - Picture shadow; - int shadow_dx; - int shadow_dy; - int shadow_width; - int shadow_height; - unsigned int opacity; - wintype window_type; - unsigned long damage_sequence; /* sequence when damage was created */ - Bool destroyed; - unsigned int left_width; - unsigned int right_width; - unsigned int top_width; - unsigned int bottom_width; - - Bool need_configure; - XConfigureEvent queue_configure; - - /* for drawing translucent windows */ - XserverRegion border_clip; - struct _win *prev_trans; -} win; - -typedef struct _conv { - int size; - double *data; -} conv; - -typedef struct _fade { - struct _fade *next; - win *w; - double cur; - double finish; - double step; - void (*callback) (Display *dpy, win *w); - Display *dpy; -} fade; - #include "compton.h" win *list; @@ -149,18 +44,12 @@ Bool win_type_fade[NUM_WINTYPES]; #define REGISTER_PROP "_NET_WM_CM_S" -#define OPAQUE 0xffffffff - conv *gaussian_map; #define WINDOW_SOLID 0 #define WINDOW_TRANS 1 #define WINDOW_ARGB 2 -#define DEBUG_REPAINT 0 -#define DEBUG_EVENTS 0 -#define MONITOR_REPAINT 0 - int shadow_radius = 12; int shadow_offset_x = -15; int shadow_offset_y = -15; diff --git a/compton.h b/compton.h index 8d3a2cb..9597871 100644 --- a/compton.h +++ b/compton.h @@ -1,4 +1,3 @@ -#if 0 #include #include #include @@ -108,7 +107,6 @@ typedef struct _fade { void (*callback) (Display *dpy, win *w); Display *dpy; } fade; -#endif int get_time_in_milliseconds(); From 69c31fc16834699c31fcb6d45f3ba5eb479d490d Mon Sep 17 00:00:00 2001 From: Christopher Jeffrey Date: Wed, 8 Feb 2012 16:45:08 -0600 Subject: [PATCH 4/5] put typedefs and defs in header. organize declarations. --- compton.c | 90 ++++++++++++++++++++++++++++++++++++------------------- compton.h | 7 +++-- 2 files changed, 64 insertions(+), 33 deletions(-) diff --git a/compton.c b/compton.c index c1c3a0b..5e2752d 100644 --- a/compton.c +++ b/compton.c @@ -14,6 +14,7 @@ win *list; fade *fades; Display *dpy; int scr; + Window root; Picture root_picture; Picture root_buffer; @@ -25,15 +26,36 @@ Bool clip_changed; Bool has_name_pixmap; #endif int root_height, root_width; + +/* errors */ ignore *ignore_head, **ignore_tail = &ignore_head; int xfixes_event, xfixes_error; int damage_event, damage_error; int composite_event, composite_error; int render_event, render_error; -Bool synchronize; int composite_opcode; -/* find these once and be done with it */ +/* shadows */ +conv *gaussian_map; + +/* for shadow precomputation */ +int Gsize = -1; +unsigned char *shadow_corner = NULL; +unsigned char *shadow_top = NULL; + +/* for root tile */ +static const char *background_props[] = { + "_XROOTPMAP_ID", + "_XSETROOT_ID", + 0, +}; + +/* for expose events */ +XRectangle *expose_rects = 0; +int size_expose = 0; +int n_expose = 0; + +/* atoms */ Atom extents_atom; Atom opacity_atom; Atom win_type_atom; @@ -42,13 +64,23 @@ double win_type_opacity[NUM_WINTYPES]; Bool win_type_shadow[NUM_WINTYPES]; Bool win_type_fade[NUM_WINTYPES]; -#define REGISTER_PROP "_NET_WM_CM_S" +/** + * Macros + */ -conv *gaussian_map; +#define INACTIVE_OPACITY \ +(unsigned long)((double)inactive_opacity * OPAQUE) -#define WINDOW_SOLID 0 -#define WINDOW_TRANS 1 -#define WINDOW_ARGB 2 +#define IS_NORMAL_WIN(w) \ +((w) && ((w)->window_type == WINTYPE_NORMAL \ + || (w)->window_type == WINTYPE_UTILITY)) +// || (w)->window_type == WINTYPE_UNKNOWN)) + +#define HAS_FRAME_OPACITY(w) (frame_opacity && (w)->top_width) + +/** + * Options + */ int shadow_radius = 12; int shadow_offset_x = -15; @@ -66,20 +98,11 @@ Bool clear_shadow = False; double inactive_opacity = 0; double frame_opacity = 0; -#define INACTIVE_OPACITY \ -(unsigned long)((double)inactive_opacity * OPAQUE) +Bool synchronize = False; -#define IS_NORMAL_WIN(w) \ -((w) && ((w)->window_type == WINTYPE_NORMAL \ - || (w)->window_type == WINTYPE_UTILITY)) -// || (w)->window_type == WINTYPE_UNKNOWN)) - -#define HAS_FRAME_OPACITY(w) (frame_opacity && (w)->top_width) - -/* For shadow precomputation */ -int Gsize = -1; -unsigned char *shadow_corner = NULL; -unsigned char *shadow_top = NULL; +/** + * Fades + */ int get_time_in_milliseconds() { @@ -278,13 +301,16 @@ run_fades(Display *dpy) { fade_time = now + fade_delta; } +/** + * Shadows + */ + static double gaussian(double r, double x, double y) { return ((1 / (sqrt(2 * M_PI * r))) * exp((- (x * x + y * y)) / (2 * r * r))); } - static conv * make_gaussian_map(Display *dpy, double r) { conv *c; @@ -636,6 +662,10 @@ solid_picture(Display *dpy, Bool argb, double a, return picture; } +/** + * Errors + */ + void discard_ignore(Display *dpy, unsigned long sequence) { while (ignore_head) { @@ -669,6 +699,10 @@ should_ignore(Display *dpy, unsigned long sequence) { return ignore_head && ignore_head->sequence == sequence; } +/** + * Windows + */ + static win * find_win(Display *dpy, Window id) { win *w; @@ -693,12 +727,6 @@ find_toplevel(Display *dpy, Window id) { return 0; } -static const char *background_props[] = { - "_XROOTPMAP_ID", - "_XSETROOT_ID", - 0, -}; - static Picture root_tile_f(Display *dpy) { Picture picture; @@ -2401,6 +2429,10 @@ get_atoms() { "_NET_WM_WINDOW_TYPE_DND", False); } +/** + * Events + */ + inline static void ev_focus_in(XFocusChangeEvent *ev) { if (!inactive_opacity) return; @@ -2469,10 +2501,6 @@ ev_circulate_notify(XCirculateEvent *ev) { circulate_win(dpy, ev); } -XRectangle *expose_rects = 0; -int size_expose = 0; -int n_expose = 0; - inline static void ev_expose(XExposeEvent *ev) { if (ev->window == root) { diff --git a/compton.h b/compton.h index 9597871..51a2646 100644 --- a/compton.h +++ b/compton.h @@ -25,6 +25,11 @@ #define MONITOR_REPAINT 0 #define OPAQUE 0xffffffff +#define REGISTER_PROP "_NET_WM_CM_S" + +#define WINDOW_SOLID 0 +#define WINDOW_TRANS 1 +#define WINDOW_ARGB 2 typedef enum { WINTYPE_UNKNOWN, @@ -340,5 +345,3 @@ handle_event(XEvent *ev); static void get_atoms(); - - From add305d69a028fab55090e02a7fda877385ddbb4 Mon Sep 17 00:00:00 2001 From: Christopher Jeffrey Date: Thu, 9 Feb 2012 03:37:46 -0600 Subject: [PATCH 5/5] move some functions around --- compton.c | 474 +++++++++++++++++++++++++++--------------------------- 1 file changed, 239 insertions(+), 235 deletions(-) diff --git a/compton.c b/compton.c index 5e2752d..e4c6e15 100644 --- a/compton.c +++ b/compton.c @@ -2075,6 +2075,205 @@ ev_window(XEvent *ev) { } #endif +/** + * Events + */ + +inline static void +ev_focus_in(XFocusChangeEvent *ev) { + if (!inactive_opacity) return; + + win *fw = find_win(dpy, ev->window); + if (IS_NORMAL_WIN(fw)) { + set_opacity(dpy, fw, OPAQUE); + } +} + +inline static void +ev_focus_out(XFocusChangeEvent *ev) { + if (!inactive_opacity) return; + + if (ev->mode == NotifyGrab + || (ev->mode == NotifyNormal + && (ev->detail == NotifyNonlinear + || ev->detail == NotifyNonlinearVirtual))) { + ; + } else { + return; + } + + win *fw = find_win(dpy, ev->window); + if (IS_NORMAL_WIN(fw)) { + set_opacity(dpy, fw, INACTIVE_OPACITY); + } +} + +inline static void +ev_create_notify(XCreateWindowEvent *ev) { + add_win(dpy, ev->window, 0, ev->override_redirect); +} + +inline static void +ev_configure_notify(XConfigureEvent *ev) { + configure_win(dpy, ev); +} + +inline static void +ev_destroy_notify(XDestroyWindowEvent *ev) { + destroy_win(dpy, ev->window, True); +} + +inline static void +ev_map_notify(XMapEvent *ev) { + map_win(dpy, ev->window, ev->serial, True, ev->override_redirect); +} + +inline static void +ev_unmap_notify(XUnmapEvent *ev) { + unmap_win(dpy, ev->window, True); +} + +inline static void +ev_reparent_notify(XReparentEvent *ev) { + if (ev->parent == root) { + add_win(dpy, ev->window, 0, ev->override_redirect); + } else { + destroy_win(dpy, ev->window, True); + } +} + +inline static void +ev_circulate_notify(XCirculateEvent *ev) { + circulate_win(dpy, ev); +} + +inline static void +ev_expose(XExposeEvent *ev) { + if (ev->window == root) { + int more = ev->count + 1; + if (n_expose == size_expose) { + if (expose_rects) { + expose_rects = realloc(expose_rects, + (size_expose + more) * sizeof(XRectangle)); + size_expose += more; + } else { + expose_rects = malloc(more * sizeof(XRectangle)); + size_expose = more; + } + } + + expose_rects[n_expose].x = ev->x; + expose_rects[n_expose].y = ev->y; + expose_rects[n_expose].width = ev->width; + expose_rects[n_expose].height = ev->height; + n_expose++; + + if (ev->count == 0) { + expose_root(dpy, root, expose_rects, n_expose); + n_expose = 0; + } + } +} + +inline static void +ev_property_notify(XPropertyEvent *ev) { + int p; + for (p = 0; background_props[p]; p++) { + if (ev->atom == XInternAtom(dpy, background_props[p], False)) { + if (root_tile) { + XClearArea(dpy, root, 0, 0, 0, 0, True); + XRenderFreePicture(dpy, root_tile); + root_tile = None; + break; + } + } + } + + /* check if Trans property was changed */ + if (ev->atom == opacity_atom) { + /* reset mode and redraw window */ + win *w = find_win(dpy, ev->window); + if (w) { + double def = win_type_opacity[w->window_type]; + set_opacity(dpy, w, + get_opacity_prop(dpy, w, (unsigned long)(OPAQUE * def))); + } + } + + if (frame_opacity && ev->atom == extents_atom) { + win *w = find_toplevel(dpy, ev->window); + if (w) { + get_frame_extents(dpy, w->client_win, + &w->left_width, &w->right_width, + &w->top_width, &w->bottom_width); + } + } +} + +inline static void +ev_damage_notify(XDamageNotifyEvent *ev) { + damage_win(dpy, ev); +} + +inline static void +handle_event(XEvent *ev) { + if ((ev->type & 0x7f) != KeymapNotify) { + discard_ignore(dpy, ev->xany.serial); + } + +#if DEBUG_EVENTS + if (ev->type != damage_event + XDamageNotify) { + printf("event %10.10s serial 0x%08x window 0x%08x\n", + ev_name(ev), ev_serial(ev), ev_window(ev)); + } +#endif + + switch (ev->type) { + case FocusIn: + ev_focus_in((XFocusChangeEvent *)ev); + break; + case FocusOut: + ev_focus_out((XFocusChangeEvent *)ev); + break; + case CreateNotify: + ev_create_notify((XCreateWindowEvent *)ev); + break; + case ConfigureNotify: + ev_configure_notify((XConfigureEvent *)ev); + break; + case DestroyNotify: + ev_destroy_notify((XDestroyWindowEvent *)ev); + break; + case MapNotify: + ev_map_notify((XMapEvent *)ev); + break; + case UnmapNotify: + ev_unmap_notify((XUnmapEvent *)ev); + break; + case ReparentNotify: + ev_reparent_notify((XReparentEvent *)ev); + break; + case CirculateNotify: + ev_circulate_notify((XCirculateEvent *)ev); + break; + case Expose: + ev_expose((XExposeEvent *)ev); + break; + case PropertyNotify: + ev_property_notify((XPropertyEvent *)ev); + break; + default: + if (ev->type == damage_event + XDamageNotify) { + ev_damage_notify((XDamageNotifyEvent *)ev); + } + break; + } +} + +/** + * Main + */ + void usage(char *program) { fprintf(stderr, "%s v0.0.1\n", program); @@ -2170,6 +2369,46 @@ register_cm(int scr) { XSetSelectionOwner(dpy, a, w, 0); } +static void +get_atoms() { + extents_atom = XInternAtom(dpy, + "_NET_FRAME_EXTENTS", False); + opacity_atom = XInternAtom(dpy, + "_NET_WM_WINDOW_OPACITY", False); + + win_type_atom = XInternAtom(dpy, + "_NET_WM_WINDOW_TYPE", False); + win_type[WINTYPE_UNKNOWN] = 0; + win_type[WINTYPE_DESKTOP] = XInternAtom(dpy, + "_NET_WM_WINDOW_TYPE_DESKTOP", False); + win_type[WINTYPE_DOCK] = XInternAtom(dpy, + "_NET_WM_WINDOW_TYPE_DOCK", False); + win_type[WINTYPE_TOOLBAR] = XInternAtom(dpy, + "_NET_WM_WINDOW_TYPE_TOOLBAR", False); + win_type[WINTYPE_MENU] = XInternAtom(dpy, + "_NET_WM_WINDOW_TYPE_MENU", False); + win_type[WINTYPE_UTILITY] = XInternAtom(dpy, + "_NET_WM_WINDOW_TYPE_UTILITY", False); + win_type[WINTYPE_SPLASH] = XInternAtom(dpy, + "_NET_WM_WINDOW_TYPE_SPLASH", False); + win_type[WINTYPE_DIALOG] = XInternAtom(dpy, + "_NET_WM_WINDOW_TYPE_DIALOG", False); + win_type[WINTYPE_NORMAL] = XInternAtom(dpy, + "_NET_WM_WINDOW_TYPE_NORMAL", False); + win_type[WINTYPE_DROPDOWN_MENU] = XInternAtom(dpy, + "_NET_WM_WINDOW_TYPE_DROPDOWN_MENU", False); + win_type[WINTYPE_POPUP_MENU] = XInternAtom(dpy, + "_NET_WM_WINDOW_TYPE_POPUP_MENU", False); + win_type[WINTYPE_TOOLTIP] = XInternAtom(dpy, + "_NET_WM_WINDOW_TYPE_TOOLTIP", False); + win_type[WINTYPE_NOTIFY] = XInternAtom(dpy, + "_NET_WM_WINDOW_TYPE_NOTIFICATION", False); + win_type[WINTYPE_COMBO] = XInternAtom(dpy, + "_NET_WM_WINDOW_TYPE_COMBO", False); + win_type[WINTYPE_DND] = XInternAtom(dpy, + "_NET_WM_WINDOW_TYPE_DND", False); +} + int main(int argc, char **argv) { XEvent ev; @@ -2389,238 +2628,3 @@ main(int argc, char **argv) { } } -static void -get_atoms() { - extents_atom = XInternAtom(dpy, - "_NET_FRAME_EXTENTS", False); - opacity_atom = XInternAtom(dpy, - "_NET_WM_WINDOW_OPACITY", False); - - win_type_atom = XInternAtom(dpy, - "_NET_WM_WINDOW_TYPE", False); - win_type[WINTYPE_UNKNOWN] = 0; - win_type[WINTYPE_DESKTOP] = XInternAtom(dpy, - "_NET_WM_WINDOW_TYPE_DESKTOP", False); - win_type[WINTYPE_DOCK] = XInternAtom(dpy, - "_NET_WM_WINDOW_TYPE_DOCK", False); - win_type[WINTYPE_TOOLBAR] = XInternAtom(dpy, - "_NET_WM_WINDOW_TYPE_TOOLBAR", False); - win_type[WINTYPE_MENU] = XInternAtom(dpy, - "_NET_WM_WINDOW_TYPE_MENU", False); - win_type[WINTYPE_UTILITY] = XInternAtom(dpy, - "_NET_WM_WINDOW_TYPE_UTILITY", False); - win_type[WINTYPE_SPLASH] = XInternAtom(dpy, - "_NET_WM_WINDOW_TYPE_SPLASH", False); - win_type[WINTYPE_DIALOG] = XInternAtom(dpy, - "_NET_WM_WINDOW_TYPE_DIALOG", False); - win_type[WINTYPE_NORMAL] = XInternAtom(dpy, - "_NET_WM_WINDOW_TYPE_NORMAL", False); - win_type[WINTYPE_DROPDOWN_MENU] = XInternAtom(dpy, - "_NET_WM_WINDOW_TYPE_DROPDOWN_MENU", False); - win_type[WINTYPE_POPUP_MENU] = XInternAtom(dpy, - "_NET_WM_WINDOW_TYPE_POPUP_MENU", False); - win_type[WINTYPE_TOOLTIP] = XInternAtom(dpy, - "_NET_WM_WINDOW_TYPE_TOOLTIP", False); - win_type[WINTYPE_NOTIFY] = XInternAtom(dpy, - "_NET_WM_WINDOW_TYPE_NOTIFICATION", False); - win_type[WINTYPE_COMBO] = XInternAtom(dpy, - "_NET_WM_WINDOW_TYPE_COMBO", False); - win_type[WINTYPE_DND] = XInternAtom(dpy, - "_NET_WM_WINDOW_TYPE_DND", False); -} - -/** - * Events - */ - -inline static void -ev_focus_in(XFocusChangeEvent *ev) { - if (!inactive_opacity) return; - - win *fw = find_win(dpy, ev->window); - if (IS_NORMAL_WIN(fw)) { - set_opacity(dpy, fw, OPAQUE); - } -} - -inline static void -ev_focus_out(XFocusChangeEvent *ev) { - if (!inactive_opacity) return; - - if (ev->mode == NotifyGrab - || (ev->mode == NotifyNormal - && (ev->detail == NotifyNonlinear - || ev->detail == NotifyNonlinearVirtual))) { - ; - } else { - return; - } - - win *fw = find_win(dpy, ev->window); - if (IS_NORMAL_WIN(fw)) { - set_opacity(dpy, fw, INACTIVE_OPACITY); - } -} - -inline static void -ev_create_notify(XCreateWindowEvent *ev) { - add_win(dpy, ev->window, 0, ev->override_redirect); -} - -inline static void -ev_configure_notify(XConfigureEvent *ev) { - configure_win(dpy, ev); -} - -inline static void -ev_destroy_notify(XDestroyWindowEvent *ev) { - destroy_win(dpy, ev->window, True); -} - -inline static void -ev_map_notify(XMapEvent *ev) { - map_win(dpy, ev->window, ev->serial, True, ev->override_redirect); -} - -inline static void -ev_unmap_notify(XUnmapEvent *ev) { - unmap_win(dpy, ev->window, True); -} - -inline static void -ev_reparent_notify(XReparentEvent *ev) { - if (ev->parent == root) { - add_win(dpy, ev->window, 0, ev->override_redirect); - } else { - destroy_win(dpy, ev->window, True); - } -} - -inline static void -ev_circulate_notify(XCirculateEvent *ev) { - circulate_win(dpy, ev); -} - -inline static void -ev_expose(XExposeEvent *ev) { - if (ev->window == root) { - int more = ev->count + 1; - if (n_expose == size_expose) { - if (expose_rects) { - expose_rects = realloc(expose_rects, - (size_expose + more) * sizeof(XRectangle)); - size_expose += more; - } else { - expose_rects = malloc(more * sizeof(XRectangle)); - size_expose = more; - } - } - - expose_rects[n_expose].x = ev->x; - expose_rects[n_expose].y = ev->y; - expose_rects[n_expose].width = ev->width; - expose_rects[n_expose].height = ev->height; - n_expose++; - - if (ev->count == 0) { - expose_root(dpy, root, expose_rects, n_expose); - n_expose = 0; - } - } -} - -inline static void -ev_property_notify(XPropertyEvent *ev) { - int p; - for (p = 0; background_props[p]; p++) { - if (ev->atom == XInternAtom(dpy, background_props[p], False)) { - if (root_tile) { - XClearArea(dpy, root, 0, 0, 0, 0, True); - XRenderFreePicture(dpy, root_tile); - root_tile = None; - break; - } - } - } - - /* check if Trans property was changed */ - if (ev->atom == opacity_atom) { - /* reset mode and redraw window */ - win *w = find_win(dpy, ev->window); - if (w) { - double def = win_type_opacity[w->window_type]; - set_opacity(dpy, w, - get_opacity_prop(dpy, w, (unsigned long)(OPAQUE * def))); - } - } - - if (frame_opacity && ev->atom == extents_atom) { - win *w = find_toplevel(dpy, ev->window); - if (w) { - get_frame_extents(dpy, w->client_win, - &w->left_width, &w->right_width, - &w->top_width, &w->bottom_width); - } - } -} - -inline static void -ev_damage_notify(XDamageNotifyEvent *ev) { - damage_win(dpy, ev); -} - -inline static void -handle_event(XEvent *ev) { - if ((ev->type & 0x7f) != KeymapNotify) { - discard_ignore(dpy, ev->xany.serial); - } - -#if DEBUG_EVENTS - if (ev->type != damage_event + XDamageNotify) { - printf("event %10.10s serial 0x%08x window 0x%08x\n", - ev_name(ev), ev_serial(ev), ev_window(ev)); - } -#endif - - switch (ev->type) { - case FocusIn: - ev_focus_in((XFocusChangeEvent *)ev); - break; - case FocusOut: - ev_focus_out((XFocusChangeEvent *)ev); - break; - case CreateNotify: - ev_create_notify((XCreateWindowEvent *)ev); - break; - case ConfigureNotify: - ev_configure_notify((XConfigureEvent *)ev); - break; - case DestroyNotify: - ev_destroy_notify((XDestroyWindowEvent *)ev); - break; - case MapNotify: - ev_map_notify((XMapEvent *)ev); - break; - case UnmapNotify: - ev_unmap_notify((XUnmapEvent *)ev); - break; - case ReparentNotify: - ev_reparent_notify((XReparentEvent *)ev); - break; - case CirculateNotify: - ev_circulate_notify((XCirculateEvent *)ev); - break; - case Expose: - ev_expose((XExposeEvent *)ev); - break; - case PropertyNotify: - ev_property_notify((XPropertyEvent *)ev); - break; - default: - if (ev->type == damage_event + XDamageNotify) { - ev_damage_notify((XDamageNotifyEvent *)ev); - } - break; - } -} -