TDE base libraries and programs
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

kompmgr.c 95KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062106310641065106610671068106910701071107210731074107510761077107810791080108110821083108410851086108710881089109010911092109310941095109610971098109911001101110211031104110511061107110811091110111111121113111411151116111711181119112011211122112311241125112611271128112911301131113211331134113511361137113811391140114111421143114411451146114711481149115011511152115311541155115611571158115911601161116211631164116511661167116811691170117111721173117411751176117711781179118011811182118311841185118611871188118911901191119211931194119511961197119811991200120112021203120412051206120712081209121012111212121312141215121612171218121912201221122212231224122512261227122812291230123112321233123412351236123712381239124012411242124312441245124612471248124912501251125212531254125512561257125812591260126112621263126412651266126712681269127012711272127312741275127612771278127912801281128212831284128512861287128812891290129112921293129412951296129712981299130013011302130313041305130613071308130913101311131213131314131513161317131813191320132113221323132413251326132713281329133013311332133313341335133613371338133913401341134213431344134513461347134813491350135113521353135413551356135713581359136013611362136313641365136613671368136913701371137213731374137513761377137813791380138113821383138413851386138713881389139013911392139313941395139613971398139914001401140214031404140514061407140814091410141114121413141414151416141714181419142014211422142314241425142614271428142914301431143214331434143514361437143814391440144114421443144414451446144714481449145014511452145314541455145614571458145914601461146214631464146514661467146814691470147114721473147414751476147714781479148014811482148314841485148614871488148914901491149214931494149514961497149814991500150115021503150415051506150715081509151015111512151315141515151615171518151915201521152215231524152515261527152815291530153115321533153415351536153715381539154015411542154315441545154615471548154915501551155215531554155515561557155815591560156115621563156415651566156715681569157015711572157315741575157615771578157915801581158215831584158515861587158815891590159115921593159415951596159715981599160016011602160316041605160616071608160916101611161216131614161516161617161816191620162116221623162416251626162716281629163016311632163316341635163616371638163916401641164216431644164516461647164816491650165116521653165416551656165716581659166016611662166316641665166616671668166916701671167216731674167516761677167816791680168116821683168416851686168716881689169016911692169316941695169616971698169917001701170217031704170517061707170817091710171117121713171417151716171717181719172017211722172317241725172617271728172917301731173217331734173517361737173817391740174117421743174417451746174717481749175017511752175317541755175617571758175917601761176217631764176517661767176817691770177117721773177417751776177717781779178017811782178317841785178617871788178917901791179217931794179517961797179817991800180118021803180418051806180718081809181018111812181318141815181618171818181918201821182218231824182518261827182818291830183118321833183418351836183718381839184018411842184318441845184618471848184918501851185218531854185518561857185818591860186118621863186418651866186718681869187018711872187318741875187618771878187918801881188218831884188518861887188818891890189118921893189418951896189718981899190019011902190319041905190619071908190919101911191219131914191519161917191819191920192119221923192419251926192719281929193019311932193319341935193619371938193919401941194219431944194519461947194819491950195119521953195419551956195719581959196019611962196319641965196619671968196919701971197219731974197519761977197819791980198119821983198419851986198719881989199019911992199319941995199619971998199920002001200220032004200520062007200820092010201120122013201420152016201720182019202020212022202320242025202620272028202920302031203220332034203520362037203820392040204120422043204420452046204720482049205020512052205320542055205620572058205920602061206220632064206520662067206820692070207120722073207420752076207720782079208020812082208320842085208620872088208920902091209220932094209520962097209820992100210121022103210421052106210721082109211021112112211321142115211621172118211921202121212221232124212521262127212821292130213121322133213421352136213721382139214021412142214321442145214621472148214921502151215221532154215521562157215821592160216121622163216421652166216721682169217021712172217321742175217621772178217921802181218221832184218521862187218821892190219121922193219421952196219721982199220022012202220322042205220622072208220922102211221222132214221522162217221822192220222122222223222422252226222722282229223022312232223322342235223622372238223922402241224222432244224522462247224822492250225122522253225422552256225722582259226022612262226322642265226622672268226922702271227222732274227522762277227822792280228122822283228422852286228722882289229022912292229322942295229622972298229923002301230223032304230523062307230823092310231123122313231423152316231723182319232023212322232323242325232623272328232923302331233223332334233523362337233823392340234123422343234423452346234723482349235023512352235323542355235623572358235923602361236223632364236523662367236823692370237123722373237423752376237723782379238023812382238323842385238623872388238923902391239223932394239523962397239823992400240124022403240424052406240724082409241024112412241324142415241624172418241924202421242224232424242524262427242824292430243124322433243424352436243724382439244024412442244324442445244624472448244924502451245224532454245524562457245824592460246124622463246424652466246724682469247024712472247324742475247624772478247924802481248224832484248524862487248824892490249124922493249424952496249724982499250025012502250325042505250625072508250925102511251225132514251525162517251825192520252125222523252425252526252725282529253025312532253325342535253625372538253925402541254225432544254525462547254825492550255125522553255425552556255725582559256025612562256325642565256625672568256925702571257225732574257525762577257825792580258125822583258425852586258725882589259025912592259325942595259625972598259926002601260226032604260526062607260826092610261126122613261426152616261726182619262026212622262326242625262626272628262926302631263226332634263526362637263826392640264126422643264426452646264726482649265026512652265326542655265626572658265926602661266226632664266526662667266826692670267126722673267426752676267726782679268026812682268326842685268626872688268926902691269226932694269526962697269826992700270127022703270427052706270727082709271027112712271327142715271627172718271927202721272227232724272527262727272827292730273127322733273427352736273727382739274027412742274327442745274627472748274927502751275227532754275527562757275827592760276127622763276427652766276727682769277027712772277327742775277627772778277927802781278227832784278527862787278827892790279127922793279427952796279727982799280028012802280328042805280628072808280928102811281228132814281528162817281828192820282128222823282428252826282728282829283028312832283328342835283628372838283928402841284228432844284528462847284828492850285128522853285428552856285728582859286028612862286328642865286628672868286928702871287228732874287528762877287828792880288128822883288428852886288728882889289028912892289328942895289628972898289929002901290229032904290529062907290829092910291129122913291429152916291729182919292029212922292329242925292629272928292929302931293229332934293529362937293829392940294129422943294429452946294729482949295029512952295329542955295629572958295929602961296229632964296529662967296829692970297129722973297429752976297729782979298029812982298329842985298629872988298929902991299229932994299529962997299829993000300130023003300430053006300730083009301030113012301330143015301630173018301930203021302230233024302530263027302830293030303130323033303430353036303730383039304030413042304330443045304630473048304930503051305230533054305530563057305830593060306130623063306430653066306730683069307030713072307330743075307630773078307930803081308230833084308530863087308830893090309130923093309430953096309730983099310031013102310331043105310631073108310931103111311231133114311531163117311831193120312131223123312431253126312731283129313031313132313331343135313631373138313931403141314231433144314531463147314831493150315131523153315431553156315731583159316031613162316331643165316631673168316931703171317231733174317531763177317831793180318131823183318431853186318731883189319031913192319331943195319631973198319932003201320232033204320532063207320832093210321132123213321432153216321732183219322032213222322332243225322632273228322932303231323232333234323532363237323832393240324132423243324432453246324732483249325032513252325332543255325632573258325932603261326232633264326532663267326832693270327132723273327432753276327732783279328032813282328332843285328632873288328932903291329232933294329532963297329832993300330133023303330433053306330733083309331033113312331333143315331633173318331933203321332233233324332533263327332833293330333133323333333433353336333733383339334033413342334333443345334633473348334933503351335233533354335533563357335833593360336133623363336433653366336733683369337033713372337333743375337633773378337933803381338233833384338533863387338833893390339133923393339433953396339733983399340034013402340334043405340634073408340934103411341234133414341534163417341834193420342134223423342434253426342734283429343034313432343334343435343634373438343934403441344234433444344534463447344834493450345134523453345434553456345734583459346034613462346334643465346634673468346934703471347234733474347534763477347834793480348134823483348434853486348734883489349034913492349334943495349634973498349935003501350235033504350535063507350835093510351135123513351435153516351735183519352035213522352335243525352635273528352935303531353235333534353535363537353835393540354135423543354435453546354735483549355035513552355335543555355635573558355935603561356235633564356535663567356835693570357135723573357435753576357735783579358035813582358335843585358635873588358935903591359235933594359535963597359835993600360136023603360436053606360736083609361036113612361336143615361636173618361936203621362236233624362536263627362836293630363136323633363436353636363736383639364036413642364336443645364636473648364936503651365236533654365536563657365836593660366136623663366436653666366736683669367036713672367336743675367636773678367936803681368236833684368536863687368836893690369136923693369436953696369736983699370037013702370337043705370637073708370937103711371237133714371537163717371837193720372137223723372437253726372737283729373037313732373337343735373637373738373937403741374237433744374537463747374837493750375137523753375437553756375737583759376037613762376337643765376637673768376937703771377237733774377537763777377837793780378137823783378437853786378737883789
  1. /*
  2. * $Id$
  3. *
  4. * Copyright © 2003 Keith Packard
  5. *
  6. * Permission to use, copy, modify, distribute, and sell this software and its
  7. * documentation for any purpose is hereby granted without fee, provided that
  8. * the above copyright notice appear in all copies and that both that
  9. * copyright notice and this permission notice appear in supporting
  10. * documentation, and that the name of Keith Packard not be used in
  11. * advertising or publicity pertaining to distribution of the software without
  12. * specific, written prior permission. Keith Packard makes no
  13. * representations about the suitability of this software for any purpose. It
  14. * is provided "as is" without express or implied warranty.
  15. *
  16. * KEITH PACKARD DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE,
  17. * INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO
  18. * EVENT SHALL KEITH PACKARD BE LIABLE FOR ANY SPECIAL, INDIRECT OR
  19. * CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE,
  20. * DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER
  21. * TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
  22. * PERFORMANCE OF THIS SOFTWARE.
  23. */
  24. /* Modified by Matthew Hawn. I don't know what to say here so follow what it
  25. says above. Not that I can really do anything about it
  26. */
  27. /* Modified by Dan Doel*/
  28. /* Modified by Timothy Pearson
  29. *
  30. * CHANGELOG:
  31. * http://patchwork.freedesktop.org/patch/1049/ [Add default background color option] 08/11/2011
  32. * http://patchwork.freedesktop.org/patch/1052/ [Prevent flicker on root pixmap change] 08/11/2011
  33. * Added SIGUSR1 handler to change process UID [Prevent flicker on login] 08/12/2011
  34. * Added ability to write PID of process to home directory 08/14/2011
  35. * Added SIGUSR2 handler to reload settings [Prevent flicker on settings change] 08/14/2011
  36. * Added SIGTERM handler to clean up stale PID files on exit 08/14/2011
  37. * Added hack to work around ATI fglrx XDamage event generation bugs [WORK_AROUND_FGLRX] 09/01/2011
  38. * Redraw root window automatically when X damage events are detected (this fixes xsetroot) 10/23/2011
  39. *
  40. * TODO:
  41. * http://patchwork.freedesktop.org/patch/1053/ [Fix window mapping with re-used window ids]
  42. */
  43. /*
  44. Version 2.x of xcompmgr, kompmgr changes by Thomas L�bking and Heiko Przybyl
  45. check baghira.sf.net for more infos
  46. */
  47. #define _VERSION_ 2.02
  48. #include <stdlib.h>
  49. #include <stdio.h>
  50. #include <string.h>
  51. #include <math.h>
  52. #include <sys/poll.h>
  53. #include <sys/time.h>
  54. #include <sys/types.h>
  55. #include <signal.h>
  56. #include <time.h>
  57. #include <unistd.h>
  58. #include <libgen.h>
  59. #include <X11/Xlib.h>
  60. #include <X11/Xutil.h>
  61. #include <X11/Xatom.h>
  62. #include <X11/extensions/Xcomposite.h>
  63. #include <X11/extensions/Xdamage.h>
  64. #include <X11/extensions/Xrender.h>
  65. #include <X11/extensions/shape.h>
  66. #if COMPOSITE_MAJOR > 0 || COMPOSITE_MINOR >= 2
  67. #define HAS_NAME_WINDOW_PIXMAP 1
  68. #endif
  69. #define CAN_DO_USABLE 1
  70. #define WORK_AROUND_FGLRX 1
  71. #define _TOPHEIGHT_(x) ((x >> 24) & 0xff)
  72. #define _RIGHTWIDTH_(x) ((x >> 16) & 0xff)
  73. #define _BOTTOMHEIGHT_(x) ((x >> 8) & 0xff)
  74. #define _LEFTWIDTH_(x) (x & 0xff)
  75. /* #define USE_ENV_HOME 1 */
  76. #define WRITE_PID_FILE 1
  77. #ifndef USE_ENV_HOME
  78. #include <pwd.h>
  79. #endif
  80. typedef enum {
  81. WINTYPE_DESKTOP,
  82. WINTYPE_DOCK,
  83. WINTYPE_TOOLBAR,
  84. WINTYPE_MENU,
  85. WINTYPE_UTILITY,
  86. WINTYPE_SPLASH,
  87. WINTYPE_DIALOG,
  88. WINTYPE_NORMAL,
  89. WINTYPE_DROPDOWN_MENU,
  90. WINTYPE_POPUP_MENU,
  91. WINTYPE_TOOLTIP,
  92. WINTYPE_NOTIFY,
  93. WINTYPE_COMBO,
  94. WINTYPE_DND,
  95. NUM_WINTYPES
  96. } wintype;
  97. typedef struct _ignore {
  98. struct _ignore *next;
  99. unsigned long sequence;
  100. } ignore;
  101. typedef struct _win {
  102. struct _win *next;
  103. Window id;
  104. #if HAS_NAME_WINDOW_PIXMAP
  105. Pixmap pixmap;
  106. #endif
  107. XWindowAttributes a;
  108. XWindowAttributes a_prev;
  109. #if CAN_DO_USABLE
  110. Bool usable; /* mapped and all damaged at one point */
  111. XRectangle damage_bounds; /* bounds of damage */
  112. #endif
  113. Bool isInFade;
  114. int mode;
  115. int damaged;
  116. Damage damage;
  117. Picture picture;
  118. Picture alphaPict;
  119. Picture shadowPict;
  120. XserverRegion borderSize;
  121. XserverRegion decoRegion;
  122. XserverRegion contentRegion;
  123. XserverRegion extents;
  124. unsigned int preShadeOpacity;
  125. Picture shadow;
  126. /*Picture alpha;*/
  127. int shadow_dx;
  128. int shadow_dy;
  129. int shadow_width;
  130. int shadow_height;
  131. unsigned int opacity;
  132. unsigned int shadowSize;
  133. wintype windowType;
  134. unsigned long damage_sequence; /* sequence when damage was created */
  135. int destroyed;
  136. Bool destruct_queued;
  137. Bool destruct_requested;
  138. int destruct_request_time;
  139. Bool shapable; /* this will allow window managers to exclude windows if just the deco is shaped*/
  140. Bool shaped;
  141. XRectangle shape_bounds;
  142. XRectangle shape_bounds_prev;
  143. unsigned int decoHash;
  144. Picture dimPicture;
  145. /* for drawing translucent windows */
  146. XserverRegion borderClip;
  147. struct _win *prev_trans;
  148. /* setting whether a window will be transparent to the desktop or the windows below it */
  149. Bool show_root_tile;
  150. } win;
  151. typedef struct _conv {
  152. int size;
  153. double *data;
  154. } conv;
  155. typedef struct _fade {
  156. struct _fade *next;
  157. win *w;
  158. double cur;
  159. double finish;
  160. double step;
  161. void (*callback) (Display *dpy, win *w, Bool gone);
  162. Display *dpy;
  163. unsigned int decoHash;
  164. Bool gone;
  165. } fade;
  166. struct sigaction usr_action;
  167. sigset_t block_mask;
  168. int my_exit_code = 3;
  169. win *list;
  170. fade *fades;
  171. Display *dpy;
  172. char *display = 0;
  173. int scr;
  174. Window root;
  175. Picture rootPicture;
  176. Picture rootBuffer;
  177. Picture blackPicture;
  178. Picture transBlackPicture;
  179. Picture rootTile;
  180. XserverRegion allDamage;
  181. Bool clipChanged;
  182. #if HAS_NAME_WINDOW_PIXMAP
  183. Bool hasNamePixmap;
  184. #endif
  185. XRenderColor fill_color;
  186. int root_height, root_width;
  187. ignore *ignore_head, **ignore_tail = &ignore_head;
  188. int xfixes_event, xfixes_error;
  189. int damage_event, damage_error;
  190. int composite_event, composite_error;
  191. int render_event, render_error;
  192. int xshape_event, xshape_error;
  193. Bool synchronize;
  194. int composite_opcode;
  195. Bool screen_damaged = False;
  196. Bool disable_argb = False;
  197. int shapeEvent;
  198. /* find these once and be done with it */
  199. Atom opacityAtom;
  200. Atom shadowAtom;
  201. Atom shadeAtom;
  202. Atom shapableAtom;
  203. Atom decoHashAtom;
  204. Atom dimAtom;
  205. Atom deskChangeAtom;
  206. Atom winTypeAtom;
  207. Atom winTDETTDAtom;
  208. Atom winType[NUM_WINTYPES];
  209. double winTypeOpacity[NUM_WINTYPES];
  210. Bool winTypeShadow[NUM_WINTYPES];
  211. Bool winTypeFade[NUM_WINTYPES];
  212. /* opacity property name; sometime soon I'll write up an EWMH spec for it */
  213. #define OPACITY_PROP "_KDE_WM_WINDOW_OPACITY"
  214. #define SHADOW_PROP "_KDE_WM_WINDOW_SHADOW"
  215. #define SHADE_PROP "_KDE_WM_WINDOW_SHADE"
  216. #define SHAPABLE_PROP "_KDE_WM_WINDOW_SHAPABLE"
  217. #define DECOHASH_PROP "_KDE_WM_WINDOW_DECOHASH"
  218. #define DIM_PROP "_KDE_WM_WINDOW_DIM"
  219. #define DESKCHANGE_PROP "_KDE_WM_DESKTOP_CHANGE"
  220. #define TRANSLUCENT 0xe0000000
  221. #define OPAQUE 0xffffffff
  222. conv *gaussianMap;
  223. #define WINDOW_SOLID 0
  224. #define WINDOW_TRANS 1
  225. #define WINDOW_ARGB 2
  226. #define TRANS_OPACITY 0.75
  227. #define NDEBUG 1
  228. #define DEBUG_REPAINT 0
  229. #define DEBUG_WINDOWS 0
  230. #define DEBUG_EVENTS 0
  231. #define MONITOR_REPAINT 0
  232. #define SHADOWS 1
  233. #define SHARP_SHADOW 0
  234. typedef enum _compMode {
  235. CompSimple, /* looks like a regular X server */
  236. CompServerShadows, /* use window alpha for shadow; sharp, but precise */
  237. CompClientShadows /* use window extents for shadow, blurred */
  238. } CompMode;
  239. static void
  240. determine_mode(Display *dpy, win *w);
  241. static double
  242. get_opacity_percent(Display *dpy, win *w);
  243. static XserverRegion
  244. win_extents (Display *dpy, win *w);
  245. static void
  246. presum_gaussian (conv *map);
  247. static conv *
  248. make_gaussian_map (Display *dpy, double r);
  249. Picture
  250. solid_picture (Display *dpy, Bool argb, double a, double r, double g, double b);
  251. CompMode compMode = CompSimple;
  252. int shadowRadius = 12;
  253. int shadowOffsetX = 0;
  254. int shadowOffsetY = 0;
  255. double shadowOpacity = .75;
  256. XRenderColor shadowColor;
  257. double fade_in_step = 0.028;
  258. double fade_out_step = 0.03;
  259. int fade_delta = 10;
  260. int fade_time = 0;
  261. Bool fadeTrans = False;
  262. Bool autoRedirect = False;
  263. #if WORK_AROUND_FGLRX
  264. Bool restartOnSigterm = True;
  265. #endif
  266. /* For shadow precomputation */
  267. int Gsize = -1;
  268. unsigned char *shadowCorner = NULL;
  269. unsigned char *shadowTop = NULL;
  270. XRenderPictFormat* sXRenderFindVisualFormat(Display *dpy, _Xconst Visual *visual)
  271. {
  272. XRenderPictFormat* format = XRenderFindVisualFormat(dpy,visual);
  273. if (format)
  274. return format;
  275. else
  276. return XRenderFindStandardFormat (dpy, PictStandardRGB24);
  277. }
  278. int
  279. get_time_in_milliseconds ()
  280. {
  281. struct timeval tv;
  282. gettimeofday (&tv, NULL);
  283. return tv.tv_sec * 1000 + tv.tv_usec / 1000;
  284. }
  285. void write_pid_file(pid_t pid)
  286. {
  287. #ifdef WRITE_PID_FILE
  288. #ifdef USE_ENV_HOME
  289. const char *home = getenv("HOME");
  290. #else
  291. const char *home;
  292. struct passwd *p;
  293. p = getpwuid(getuid());
  294. if (p)
  295. home = p->pw_dir;
  296. else
  297. home = getenv("HOME");
  298. #endif
  299. const char *filename;
  300. const char *configfile = "/.kompmgr.pid";
  301. int n = strlen(home)+strlen(configfile)+1;
  302. filename = (char*)malloc(n*sizeof(char));
  303. memset(filename,0,n);
  304. strcat(filename, home);
  305. strcat(filename, configfile);
  306. printf("writing '%s' as pidfile\n\n", filename);
  307. /* now that we did all that by way of introduction...write the file! */
  308. FILE *pFile;
  309. char buffer[255];
  310. sprintf(buffer, "%d", pid);
  311. pFile = fopen(filename, "w");
  312. if (pFile) {
  313. fwrite(buffer,1,strlen(buffer), pFile);
  314. fclose(pFile);
  315. }
  316. free(filename);
  317. filename = NULL;
  318. #endif
  319. }
  320. void delete_pid_file()
  321. {
  322. #ifdef WRITE_PID_FILE
  323. #ifdef USE_ENV_HOME
  324. const char *home = getenv("HOME");
  325. #else
  326. const char *home;
  327. struct passwd *p;
  328. p = getpwuid(getuid());
  329. if (p)
  330. home = p->pw_dir;
  331. else
  332. home = getenv("HOME");
  333. #endif
  334. const char *filename;
  335. const char *configfile = "/.kompmgr.pid";
  336. int n = strlen(home)+strlen(configfile)+1;
  337. filename = (char*)malloc(n*sizeof(char));
  338. memset(filename,0,n);
  339. strcat(filename, home);
  340. strcat(filename, configfile);
  341. printf("deleting '%s' as pidfile\n\n", filename);
  342. /* now that we did all that by way of introduction...delete the file! */
  343. unlink(filename);
  344. free(filename);
  345. filename = NULL;
  346. #endif
  347. #if WORK_AROUND_FGLRX
  348. if ((my_exit_code == 3) && (restartOnSigterm)) {
  349. printf("kompmgr lost connection to X server, restarting...\n"); fflush(stdout);
  350. sleep(1);
  351. char me[2048];
  352. int chars = readlink("/proc/self/exe", me, sizeof(me));
  353. me[chars] = 0;
  354. me[2047] = 0;
  355. execl(me, basename(me), (char*)NULL);
  356. }
  357. #endif
  358. }
  359. void clear_shadow_cache()
  360. {
  361. win *w;
  362. for (w = list; w; w = w->next) {
  363. if (w->shadow)
  364. {
  365. XRenderFreePicture (dpy, w->shadow);
  366. w->shadow = None;
  367. if (w->opacity != OPAQUE && !w->alphaPict)
  368. w->alphaPict = solid_picture (dpy, False,
  369. (double) w->opacity / OPAQUE, shadowColor.red, shadowColor.green, shadowColor.blue);
  370. if( w->extents != None ) {
  371. XFixesDestroyRegion( dpy, w->extents );
  372. }
  373. w->extents = win_extents (dpy, w);
  374. w->damaged = 1; /* redraw */
  375. }
  376. }
  377. }
  378. void handle_siguser (int sig)
  379. {
  380. int uidnum;
  381. if (sig == SIGTERM) {
  382. // Trap this signal and keep running...
  383. return;
  384. }
  385. if (sig == SIGUSR1) {
  386. char newuid[1024];
  387. #ifndef NDEBUG
  388. printf("Enter the new user ID:\n"); fflush(stdout);
  389. #endif
  390. char *eof;
  391. newuid[0] = '\0';
  392. newuid[sizeof(newuid)-1] = '\0';
  393. eof = fgets(newuid, sizeof(newuid), stdin);
  394. uidnum = atoi(newuid);
  395. #ifndef NDEBUG
  396. printf("Setting kompmgr process uid to %d...\n", uidnum); fflush(stdout);
  397. #endif
  398. my_exit_code=4;
  399. delete_pid_file();
  400. my_exit_code=3;
  401. setuid(uidnum);
  402. write_pid_file(getpid());
  403. }
  404. else {
  405. uidnum = getuid();
  406. }
  407. if ((sig == SIGUSR1) || (sig == SIGUSR2)) {
  408. #ifdef USE_ENV_HOME
  409. const char *home = getenv("HOME");
  410. #else
  411. const char *home;
  412. struct passwd *p;
  413. p = getpwuid(uidnum);
  414. if (p)
  415. home = p->pw_dir;
  416. else
  417. home = getenv("HOME");
  418. #endif
  419. const char *filename;
  420. const char *configfile = "/.xcompmgrrc";
  421. int n = strlen(home)+strlen(configfile)+1;
  422. filename = (char*)malloc(n*sizeof(char));
  423. memset(filename,0,n);
  424. strcat(filename, home);
  425. strcat(filename, configfile);
  426. loadConfig(filename); /* reload the configuration file */
  427. /* set background/shadow picture using the new settings */
  428. blackPicture = solid_picture (dpy, True, 1, (double)(shadowColor.red)/0xff, (double)(shadowColor.green)/0xff, (double)(shadowColor.blue)/0xff);
  429. if (compMode == CompServerShadows)
  430. transBlackPicture = solid_picture (dpy, True, 0.3, 0, 0, 0);
  431. /* regenerate shadows using the new settings */
  432. if (compMode == CompClientShadows)
  433. {
  434. gaussianMap = make_gaussian_map(dpy, shadowRadius);
  435. presum_gaussian (gaussianMap);
  436. }
  437. clear_shadow_cache();
  438. free(filename);
  439. filename = NULL;
  440. }
  441. }
  442. fade *
  443. find_fade (win *w)
  444. {
  445. fade *f;
  446. for (f = fades; f; f = f->next)
  447. {
  448. if (f->w == w)
  449. return f;
  450. }
  451. return 0;
  452. }
  453. void dequeue_fade (Display *dpy, fade *f)
  454. {
  455. fade **prev;
  456. f->w->isInFade = False;
  457. f->w->decoHash = f->decoHash;
  458. for (prev = &fades; *prev; prev = &(*prev)->next)
  459. if (*prev == f)
  460. {
  461. *prev = f->next;
  462. if (f->callback)
  463. {
  464. (*f->callback) (dpy, f->w, f->gone);
  465. }
  466. free (f);
  467. break;
  468. }
  469. }
  470. void
  471. cleanup_fade (Display *dpy, win *w)
  472. {
  473. fade *f = find_fade (w);
  474. if (f)
  475. dequeue_fade (dpy, f);
  476. }
  477. void
  478. enqueue_fade (Display *dpy, fade *f)
  479. {
  480. f->w->isInFade = True;
  481. if (!fades)
  482. fade_time = get_time_in_milliseconds () + fade_delta;
  483. f->next = fades;
  484. fades = f;
  485. }
  486. static void unmap_callback (Display *dpy, win *w, Bool gone);
  487. static void
  488. set_fade (Display *dpy, win *w, double start, double finish, double step,
  489. void (*callback) (Display *dpy, win *w, Bool gone),
  490. Bool gone, Bool exec_callback, Bool override, Bool wholeWin)
  491. {
  492. fade *f;
  493. f = find_fade (w);
  494. if (!f)
  495. {
  496. if (start == finish)
  497. return;
  498. f = malloc (sizeof (fade));
  499. f->next = 0;
  500. f->w = w;
  501. f->decoHash = w->decoHash;
  502. f->cur = start;
  503. enqueue_fade (dpy, f);
  504. }
  505. else if(!override)
  506. return;
  507. else
  508. {
  509. if (exec_callback && f->callback)
  510. (*f->callback)(dpy, f->w, f->gone);
  511. }
  512. if (finish < 0)
  513. finish = 0;
  514. if (finish > 1)
  515. finish = 1;
  516. f->finish = finish;
  517. if (f->cur < finish)
  518. f->step = step;
  519. else if (f->cur > finish)
  520. f->step = -step;
  521. f->gone = gone && (exec_callback || f->callback != unmap_callback);
  522. f->callback = callback;
  523. w->opacity = f->cur * OPAQUE;
  524. if (wholeWin)
  525. w->decoHash = 0;
  526. #if 0
  527. printf ("set_fade start %g step %g\n", f->cur, f->step);
  528. #endif
  529. determine_mode (dpy, w);
  530. if (w->shadow)
  531. {
  532. XRenderFreePicture (dpy, w->shadow);
  533. w->shadow = None;
  534. if( w->extents != None )
  535. XFixesDestroyRegion( dpy, w->extents );
  536. w->extents = win_extents (dpy, w);
  537. }
  538. /* fading windows need to be drawn, mark them as damaged.
  539. when a window maps, if it tries to fade in but it already at the right
  540. opacity (map/unmap/map fast) then it will never get drawn without this
  541. until it repaints */
  542. w->damaged = 1;
  543. }
  544. int
  545. fade_timeout (void)
  546. {
  547. int now;
  548. int delta;
  549. if (!fades)
  550. return -1;
  551. now = get_time_in_milliseconds();
  552. delta = fade_time - now;
  553. if (delta < 0)
  554. delta = 0;
  555. /* printf ("timeout %d\n", delta); */
  556. return delta;
  557. }
  558. void
  559. run_fades (Display *dpy)
  560. {
  561. int now = get_time_in_milliseconds();
  562. fade *f, *next;
  563. int steps;
  564. Bool need_dequeue;
  565. #if 0
  566. printf ("run fades\n");
  567. #endif
  568. if (fade_time - now > 0)
  569. return;
  570. steps = 1 + (now - fade_time) / fade_delta;
  571. for (next = fades; (f = next); )
  572. {
  573. win *w = f->w;
  574. next = f->next;
  575. f->cur += f->step * steps;
  576. if (f->cur >= 1)
  577. f->cur = 1;
  578. else if (f->cur < 0)
  579. f->cur = 0;
  580. #if 0
  581. printf ("opacity now %g -> %g\n", f->cur, f->finish);
  582. #endif
  583. w->opacity = f->cur * OPAQUE;
  584. need_dequeue = False;
  585. if (f->step > 0)
  586. {
  587. if (f->cur >= f->finish)
  588. {
  589. w->opacity = f->finish*OPAQUE;
  590. need_dequeue = True;
  591. }
  592. }
  593. else
  594. {
  595. if (f->cur <= f->finish)
  596. {
  597. w->opacity = f->finish*OPAQUE;
  598. need_dequeue = True;
  599. }
  600. }
  601. if (w->shadow)
  602. {
  603. XRenderFreePicture (dpy, w->shadow);
  604. w->shadow = None;
  605. if( w->extents != None )
  606. XFixesDestroyRegion( dpy, w->extents );
  607. w->extents = win_extents(dpy, w);
  608. }
  609. determine_mode (dpy, w);
  610. /* Must do this last as it might destroy f->w in callbacks */
  611. if (need_dequeue)
  612. dequeue_fade (dpy, f);
  613. }
  614. fade_time = now + fade_delta;
  615. }
  616. #define SHADOW_OFFSET_X ((-shadowRadius * 7 / 5) - shadowOffsetX * shadowRadius / 100) * w->shadowSize
  617. #define SHADOW_OFFSET_Y ((-shadowRadius * 7 / 5) - shadowOffsetY * shadowRadius / 100) * w->shadowSize
  618. /*#define SHADOW_OFFSET_X (w->shadowSize * -shadowRadius * 7 / 500) - w->shadowSize * shadowOffsetX * shadowRadius / 10000
  619. #define SHADOW_OFFSET_Y (w->shadowSize * -shadowRadius * 7 / 500) - w->shadowSize * shadowOffsetY * shadowRadius / 10000*/
  620. static double
  621. gaussian (double r, double x, double y)
  622. {
  623. return ((1 / (sqrt (2 * M_PI * r))) *
  624. exp ((- (x * x + y * y)) / (2 * r * r)));
  625. }
  626. static conv *
  627. make_gaussian_map (Display *dpy, double r)
  628. {
  629. conv *c;
  630. int size = ((int) ceil ((r * 3)) + 1) & ~1;
  631. int center = size / 2;
  632. int x, y;
  633. double t;
  634. double g;
  635. c = malloc (sizeof (conv) + size * size * sizeof (double));
  636. c->size = size;
  637. c->data = (double *) (c + 1);
  638. t = 0.0;
  639. for (y = 0; y < size; y++)
  640. for (x = 0; x < size; x++)
  641. {
  642. g = gaussian (r, (double) (x - center), (double) (y - center));
  643. t += g;
  644. c->data[y * size + x] = g;
  645. }
  646. /* printf ("gaussian total %f\n", t); */
  647. for (y = 0; y < size; y++)
  648. for (x = 0; x < size; x++)
  649. {
  650. c->data[y*size + x] /= t;
  651. }
  652. return c;
  653. }
  654. /*
  655. * A picture will help
  656. *
  657. * -center 0 width width+center
  658. * -center +-----+-------------------+-----+
  659. * | | | |
  660. * | | | |
  661. * 0 +-----+-------------------+-----+
  662. * | | | |
  663. * | | | |
  664. * | | | |
  665. * height +-----+-------------------+-----+
  666. * | | | |
  667. * height+ | | | |
  668. * center +-----+-------------------+-----+
  669. */
  670. static unsigned char
  671. sum_gaussian (conv *map, double opacity, int x, int y, int width, int height)
  672. {
  673. int fx, fy;
  674. double *g_data;
  675. double *g_line = map->data;
  676. int g_size = map->size;
  677. int center = g_size / 2;
  678. int fx_start, fx_end;
  679. int fy_start, fy_end;
  680. double v;
  681. /*
  682. * Compute set of filter values which are "in range",
  683. * that's the set with:
  684. * 0 <= x + (fx-center) && x + (fx-center) < width &&
  685. * 0 <= y + (fy-center) && y + (fy-center) < height
  686. *
  687. * 0 <= x + (fx - center) x + fx - center < width
  688. * center - x <= fx fx < width + center - x
  689. */
  690. fx_start = center - x;
  691. if (fx_start < 0)
  692. fx_start = 0;
  693. fx_end = width + center - x;
  694. if (fx_end > g_size)
  695. fx_end = g_size;
  696. fy_start = center - y;
  697. if (fy_start < 0)
  698. fy_start = 0;
  699. fy_end = height + center - y;
  700. if (fy_end > g_size)
  701. fy_end = g_size;
  702. g_line = g_line + fy_start * g_size + fx_start;
  703. v = 0;
  704. for (fy = fy_start; fy < fy_end; fy++)
  705. {
  706. g_data = g_line;
  707. g_line += g_size;
  708. for (fx = fx_start; fx < fx_end; fx++)
  709. v += *g_data++;
  710. }
  711. if (v > 1)
  712. v = 1;
  713. return ((unsigned char) (v * opacity * 255.0));
  714. }
  715. /* precompute shadow corners and sides to save time for large windows */
  716. static void
  717. presum_gaussian (conv *map)
  718. {
  719. int center = map->size/2;
  720. int opacity, x, y;
  721. Gsize = map->size;
  722. if (shadowCorner)
  723. free ((void *)shadowCorner);
  724. if (shadowTop)
  725. free ((void *)shadowTop);
  726. shadowCorner = (unsigned char *)(malloc ((Gsize + 1) * (Gsize + 1) * 26));
  727. shadowTop = (unsigned char *)(malloc ((Gsize + 1) * 26));
  728. for (x = 0; x <= Gsize; x++)
  729. {
  730. shadowTop[25 * (Gsize + 1) + x] = sum_gaussian (map, 1, x - center, center, Gsize * 2, Gsize * 2);
  731. for(opacity = 0; opacity < 25; opacity++)
  732. shadowTop[opacity * (Gsize + 1) + x] = shadowTop[25 * (Gsize + 1) + x] * opacity / 25;
  733. for(y = 0; y <= x; y++)
  734. {
  735. shadowCorner[25 * (Gsize + 1) * (Gsize + 1) + y * (Gsize + 1) + x]
  736. = sum_gaussian (map, 1, x - center, y - center, Gsize * 2, Gsize * 2);
  737. shadowCorner[25 * (Gsize + 1) * (Gsize + 1) + x * (Gsize + 1) + y]
  738. = shadowCorner[25 * (Gsize + 1) * (Gsize + 1) + y * (Gsize + 1) + x];
  739. for(opacity = 0; opacity < 25; opacity++)
  740. shadowCorner[opacity * (Gsize + 1) * (Gsize + 1) + y * (Gsize + 1) + x]
  741. = shadowCorner[opacity * (Gsize + 1) * (Gsize + 1) + x * (Gsize + 1) + y]
  742. = shadowCorner[25 * (Gsize + 1) * (Gsize + 1) + y * (Gsize + 1) + x] * opacity / 25;
  743. }
  744. }
  745. }
  746. static XImage *
  747. make_shadow (Display *dpy, double opacity, int width, int height)
  748. {
  749. XImage *ximage;
  750. unsigned char *data;
  751. int gsize = gaussianMap->size;
  752. int ylimit, xlimit;
  753. int swidth = width + gsize;
  754. int sheight = height + gsize;
  755. int center = gsize / 2;
  756. int x, y;
  757. unsigned char d;
  758. int x_diff;
  759. int opacity_int = (int)(opacity * 25);
  760. data = malloc (swidth * sheight * sizeof (unsigned char));
  761. if (!data)
  762. return 0;
  763. ximage = XCreateImage (dpy,
  764. DefaultVisual(dpy, DefaultScreen(dpy)),
  765. 8,
  766. ZPixmap,
  767. 0,
  768. (char *) data,
  769. swidth, sheight, 8, swidth * sizeof (unsigned char));
  770. if (!ximage)
  771. {
  772. free (data);
  773. return 0;
  774. }
  775. /*
  776. * Build the gaussian in sections
  777. */
  778. /*
  779. * center (fill the complete data array)
  780. */
  781. if (Gsize > 0)
  782. d = shadowTop[opacity_int * (Gsize + 1) + Gsize];
  783. else
  784. d = sum_gaussian (gaussianMap, opacity, center, center, width, height);
  785. memset(data, d, sheight * swidth);
  786. /*
  787. * corners
  788. */
  789. ylimit = gsize;
  790. if (ylimit > sheight / 2)
  791. ylimit = (sheight + 1) / 2;
  792. xlimit = gsize;
  793. if (xlimit > swidth / 2)
  794. xlimit = (swidth + 1) / 2;
  795. for (y = 0; y < ylimit; y++)
  796. for (x = 0; x < xlimit; x++)
  797. {
  798. if (xlimit == Gsize && ylimit == Gsize)
  799. d = shadowCorner[opacity_int * (Gsize + 1) * (Gsize + 1) + y * (Gsize + 1) + x];
  800. else
  801. d = sum_gaussian (gaussianMap, opacity, x - center, y - center, width, height);
  802. data[y * swidth + x] = d;
  803. data[(sheight - y - 1) * swidth + x] = d;
  804. data[(sheight - y - 1) * swidth + (swidth - x - 1)] = d;
  805. data[y * swidth + (swidth - x - 1)] = d;
  806. }
  807. /*
  808. * top/bottom
  809. */
  810. x_diff = swidth - (gsize * 2);
  811. if (x_diff > 0 && ylimit > 0)
  812. {
  813. for (y = 0; y < ylimit; y++)
  814. {
  815. if (ylimit == Gsize)
  816. d = shadowTop[opacity_int * (Gsize + 1) + y];
  817. else
  818. d = sum_gaussian (gaussianMap, opacity, center, y - center, width, height);
  819. memset (&data[y * swidth + gsize], d, x_diff);
  820. memset (&data[(sheight - y - 1) * swidth + gsize], d, x_diff);
  821. }
  822. }
  823. /*
  824. * sides
  825. */
  826. for (x = 0; x < xlimit; x++)
  827. {
  828. if (xlimit == Gsize)
  829. d = shadowTop[opacity_int * (Gsize + 1) + x];
  830. else
  831. d = sum_gaussian (gaussianMap, opacity, x - center, center, width, height);
  832. for (y = gsize; y < sheight - gsize; y++)
  833. {
  834. data[y * swidth + x] = d;
  835. data[y * swidth + (swidth - x - 1)] = d;
  836. }
  837. }
  838. return ximage;
  839. }
  840. static Picture
  841. shadow_picture (Display *dpy, double opacity, Picture alpha_pict, int width, int height, int *wp, int *hp)
  842. {
  843. XImage *shadowImage;
  844. Pixmap shadowPixmap;
  845. Pixmap finalPixmap;
  846. Picture shadowPicture;
  847. Picture finalPicture;
  848. GC gc;
  849. shadowImage = make_shadow (dpy, opacity, width, height);
  850. if (!shadowImage)
  851. return None;
  852. shadowPixmap = XCreatePixmap (dpy, root,
  853. shadowImage->width,
  854. shadowImage->height,
  855. 8);
  856. if (!shadowPixmap)
  857. {
  858. XDestroyImage (shadowImage);
  859. return None;
  860. }
  861. shadowPicture = XRenderCreatePicture (dpy, shadowPixmap,
  862. XRenderFindStandardFormat (dpy, PictStandardA8),
  863. 0, 0);
  864. if (!shadowPicture)
  865. {
  866. XDestroyImage (shadowImage);
  867. XFreePixmap (dpy, shadowPixmap);
  868. return None;
  869. }
  870. gc = XCreateGC (dpy, shadowPixmap, 0, 0);
  871. if (!gc)
  872. {
  873. XDestroyImage (shadowImage);
  874. XFreePixmap (dpy, shadowPixmap);
  875. XRenderFreePicture (dpy, shadowPicture);
  876. return None;
  877. }
  878. XPutImage (dpy, shadowPixmap, gc, shadowImage, 0, 0, 0, 0,
  879. shadowImage->width,
  880. shadowImage->height);
  881. *wp = shadowImage->width;
  882. *hp = shadowImage->height;
  883. XFreeGC (dpy, gc);
  884. XDestroyImage (shadowImage);
  885. XFreePixmap (dpy, shadowPixmap);
  886. return shadowPicture;
  887. }
  888. Picture
  889. solid_picture (Display *dpy, Bool argb, double a, double r, double g, double b)
  890. {
  891. Pixmap pixmap;
  892. Picture picture;
  893. XRenderPictureAttributes pa;
  894. XRenderColor c;
  895. pixmap = XCreatePixmap (dpy, root, 1, 1, argb ? 32 : 8);
  896. if (!pixmap)
  897. return None;
  898. pa.repeat = True;
  899. picture = XRenderCreatePicture (dpy, pixmap,
  900. XRenderFindStandardFormat (dpy, argb ? PictStandardARGB32 : PictStandardA8),
  901. CPRepeat,
  902. &pa);
  903. if (!picture)
  904. {
  905. XFreePixmap (dpy, pixmap);
  906. return None;
  907. }
  908. c.alpha = a * 0xffff;
  909. c.red = r * 0xffff;
  910. c.green = g * 0xffff;
  911. c.blue = b * 0xffff;
  912. XRenderFillRectangle (dpy, PictOpSrc, picture, &c, 0, 0, 1, 1);
  913. XFreePixmap (dpy, pixmap);
  914. return picture;
  915. }
  916. void
  917. discard_ignore (Display *dpy, unsigned long sequence)
  918. {
  919. while (ignore_head)
  920. {
  921. if ((long) (sequence - ignore_head->sequence) > 0)
  922. {
  923. ignore *next = ignore_head->next;
  924. free (ignore_head);
  925. ignore_head = next;
  926. if (!ignore_head)
  927. ignore_tail = &ignore_head;
  928. }
  929. else
  930. break;
  931. }
  932. }
  933. void
  934. set_ignore (Display *dpy, unsigned long sequence)
  935. {
  936. ignore *i = malloc (sizeof (ignore));
  937. if (!i)
  938. return;
  939. i->sequence = sequence;
  940. i->next = 0;
  941. *ignore_tail = i;
  942. ignore_tail = &i->next;
  943. }
  944. int
  945. should_ignore (Display *dpy, unsigned long sequence)
  946. {
  947. discard_ignore (dpy, sequence);
  948. return ignore_head && ignore_head->sequence == sequence;
  949. }
  950. static win *
  951. find_win (Display *dpy, Window id)
  952. {
  953. win *w;
  954. for (w = list; w; w = w->next)
  955. if ((!w->destroyed) && (w->id == id))
  956. return w;
  957. return 0;
  958. }
  959. static char *backgroundProps[] = {
  960. "_XROOTPMAP_ID",
  961. "_XSETROOT_ID",
  962. 0,
  963. };
  964. static Picture
  965. root_tile (Display *dpy)
  966. {
  967. Picture picture;
  968. Atom actual_type;
  969. Pixmap pixmap;
  970. int actual_format;
  971. unsigned long nitems;
  972. unsigned long bytes_after;
  973. unsigned char *prop;
  974. Bool fill;
  975. XRenderPictureAttributes pa;
  976. int p;
  977. pixmap = None;
  978. for (p = 0; backgroundProps[p]; p++)
  979. {
  980. if (XGetWindowProperty (dpy, root, XInternAtom (dpy, backgroundProps[p], False),
  981. 0, 4, False, AnyPropertyType,
  982. &actual_type, &actual_format, &nitems, &bytes_after, &prop) == Success &&
  983. actual_type == XInternAtom (dpy, "PIXMAP", False) && actual_format == 32 && nitems == 1)
  984. {
  985. pixmap = *(long*)prop;
  986. XFree (prop);
  987. fill = False;
  988. break;
  989. }
  990. }
  991. if (!pixmap)
  992. {
  993. pixmap = XCreatePixmap (dpy, root, 1, 1, DefaultDepth (dpy, scr));
  994. fill = True;
  995. }
  996. pa.repeat = True;
  997. picture = XRenderCreatePicture (dpy, pixmap,
  998. sXRenderFindVisualFormat (dpy,
  999. DefaultVisual (dpy, scr)),
  1000. CPRepeat, &pa);
  1001. if (fill)
  1002. {
  1003. XRenderFillRectangle (dpy, PictOpSrc, picture, &fill_color,
  1004. 0, 0, 1, 1);
  1005. }
  1006. return picture;
  1007. }
  1008. static void
  1009. paint_root (Display *dpy)
  1010. {
  1011. if (!rootTile)
  1012. rootTile = root_tile (dpy);
  1013. XRenderComposite (dpy, PictOpSrc,
  1014. rootTile, None, rootBuffer,
  1015. 0, 0, 0, 0, 0, 0, root_width, root_height);
  1016. }
  1017. static XserverRegion
  1018. win_extents (Display *dpy, win *w)
  1019. {
  1020. XRectangle r;
  1021. r.x = w->a.x;
  1022. r.y = w->a.y;
  1023. r.width = w->a.width + w->a.border_width * 2;
  1024. r.height = w->a.height + w->a.border_width * 2;
  1025. if (winTypeShadow[w->windowType])
  1026. {
  1027. if (compMode == CompServerShadows || w->mode != WINDOW_ARGB)
  1028. {
  1029. XRectangle sr;
  1030. if (compMode == CompServerShadows)
  1031. {
  1032. w->shadow_dx = 2;
  1033. w->shadow_dy = 7;
  1034. w->shadow_width = w->a.width;
  1035. w->shadow_height = w->a.height;
  1036. }
  1037. else
  1038. {
  1039. w->shadow_dx = SHADOW_OFFSET_X;
  1040. w->shadow_dx = w->shadow_dx / 100;
  1041. w->shadow_dy = SHADOW_OFFSET_Y;
  1042. w->shadow_dy = w->shadow_dy / 100;
  1043. if (!w->shadow)
  1044. {
  1045. double opacity = shadowOpacity;
  1046. if (w->shadowSize > 100)
  1047. opacity = opacity/(w->shadowSize*0.015);
  1048. if (w->mode == WINDOW_TRANS)
  1049. opacity = opacity * ((double)w->opacity)/((double)OPAQUE);
  1050. w->shadow = shadow_picture (dpy, opacity, w->alphaPict,
  1051. w->a.width + w->a.border_width * 2 - 2*(shadowRadius - (w->shadowSize*shadowRadius/100)) ,
  1052. w->a.height + w->a.border_width * 2 - 2*(shadowRadius - (w->shadowSize*shadowRadius/100)),
  1053. &w->shadow_width, &w->shadow_height);
  1054. /*int kill;
  1055. w->alpha = shadow_picture (dpy, 0.9, w->alphaPict,
  1056. w->a.width + w->a.border_width * 2,
  1057. w->a.height + w->a.border_width * 2,
  1058. &kill, &kill);*/
  1059. }
  1060. }
  1061. sr.x = w->a.x + w->shadow_dx;
  1062. sr.y = w->a.y + w->shadow_dy;
  1063. sr.width = w->shadow_width;
  1064. sr.height = w->shadow_height;
  1065. if (sr.x < r.x)
  1066. {
  1067. r.width = (r.x + r.width) - sr.x;
  1068. r.x = sr.x;
  1069. }
  1070. if (sr.y < r.y)
  1071. {
  1072. r.height = (r.y + r.height) - sr.y;
  1073. r.y = sr.y;
  1074. }
  1075. if (sr.x + sr.width > r.x + r.width)
  1076. r.width = sr.x + sr.width - r.x;
  1077. if (sr.y + sr.height > r.y + r.height)
  1078. r.height = sr.y + sr.height - r.y;
  1079. }
  1080. }
  1081. return XFixesCreateRegion (dpy, &r, 1);
  1082. }
  1083. static XserverRegion
  1084. border_size (Display *dpy, win *w)
  1085. {
  1086. XserverRegion border;
  1087. /*
  1088. * if window doesn't exist anymore, this will generate an error
  1089. * as well as not generate a region. Perhaps a better XFixes
  1090. * architecture would be to have a request that copies instead
  1091. * of creates, that way you'd just end up with an empty region
  1092. * instead of an invalid XID.
  1093. */
  1094. set_ignore (dpy, NextRequest (dpy));
  1095. border = XFixesCreateRegionFromWindow (dpy, w->id, WindowRegionBounding);
  1096. /* translate this */
  1097. set_ignore (dpy, NextRequest (dpy));
  1098. XFixesTranslateRegion (dpy, border,
  1099. w->a.x + w->a.border_width,
  1100. w->a.y + w->a.border_width);
  1101. return border;
  1102. }
  1103. static XserverRegion
  1104. deco_region (Display *dpy, win *w)
  1105. {
  1106. XserverRegion title;
  1107. XRectangle r; /*titlebounding rect*/
  1108. /*
  1109. * if window doesn't exist anymore, this will generate an error
  1110. * as well as not generate a region. Perhaps a better XFixes
  1111. * architecture would be to have a request that copies instead
  1112. * of creates, that way you'd just end up with an empty region
  1113. * instead of an invalid XID.
  1114. */
  1115. r.x = w->a.x - w->a.border_width + _LEFTWIDTH_(w->decoHash);
  1116. r.y = w->a.y - w->a.border_width + _TOPHEIGHT_(w->decoHash);
  1117. r.width = w->a.width + w->a.border_width * 2 - _LEFTWIDTH_(w->decoHash) - _RIGHTWIDTH_(w->decoHash);
  1118. r.height = w->a.height + w->a.border_width - _TOPHEIGHT_(w->decoHash) - _BOTTOMHEIGHT_(w->decoHash);
  1119. set_ignore (dpy, NextRequest (dpy));
  1120. title = XFixesCreateRegion (dpy, &r, 1);
  1121. if (!w->borderSize)
  1122. w->borderSize = border_size (dpy, w);
  1123. set_ignore (dpy, NextRequest (dpy));
  1124. XFixesSubtractRegion(dpy, title, w->borderSize, title);
  1125. return title;
  1126. }
  1127. static void finish_destroy_win (Display *dpy, Window id, Bool gone);
  1128. static XserverRegion
  1129. content_region (Display *dpy, win *w)
  1130. {
  1131. XserverRegion content;
  1132. XRectangle r; /*contentbounding rect*/
  1133. /*
  1134. * if window doesn't exist anymore, this will generate an error
  1135. * as well as not generate a region. Perhaps a better XFixes
  1136. * architecture would be to have a request that copies instead
  1137. * of creates, that way you'd just end up with an empty region
  1138. * instead of an invalid XID.
  1139. */
  1140. r.x = w->a.x - w->a.border_width + _LEFTWIDTH_(w->decoHash);
  1141. r.y = w->a.y - w->a.border_width + _TOPHEIGHT_(w->decoHash);
  1142. r.width = w->a.width + w->a.border_width * 2 - _LEFTWIDTH_(w->decoHash) - _RIGHTWIDTH_(w->decoHash);
  1143. r.height = w->a.height + w->a.border_width - _TOPHEIGHT_(w->decoHash) - _BOTTOMHEIGHT_(w->decoHash);
  1144. set_ignore (dpy, NextRequest (dpy));
  1145. content = XFixesCreateRegion (dpy, &r, 1);
  1146. if (!w->borderSize)
  1147. w->borderSize = border_size (dpy, w);
  1148. set_ignore (dpy, NextRequest (dpy));
  1149. XFixesIntersectRegion(dpy, content, w->borderSize, content);
  1150. return content;
  1151. }
  1152. static void
  1153. paint_all (Display *dpy, XserverRegion region)
  1154. {
  1155. win *w;
  1156. win *t = 0;
  1157. #if DEBUG_WINDOWS
  1158. int window_count = 0;
  1159. #endif
  1160. if (!region)
  1161. {
  1162. XRectangle r;
  1163. r.x = 0;
  1164. r.y = 0;
  1165. r.width = root_width;
  1166. r.height = root_height;
  1167. region = XFixesCreateRegion (dpy, &r, 1);
  1168. }
  1169. #if MONITOR_REPAINT
  1170. rootBuffer = rootPicture;
  1171. #else
  1172. if (!rootBuffer)
  1173. {
  1174. Pixmap rootPixmap = XCreatePixmap (dpy, root, root_width, root_height,
  1175. DefaultDepth (dpy, scr));
  1176. rootBuffer = XRenderCreatePicture (dpy, rootPixmap,
  1177. sXRenderFindVisualFormat (dpy,
  1178. DefaultVisual (dpy, scr)),
  1179. 0, 0);
  1180. XFreePixmap (dpy, rootPixmap);
  1181. }
  1182. #endif
  1183. XFixesSetPictureClipRegion (dpy, rootPicture, 0, 0, region);
  1184. #if MONITOR_REPAINT
  1185. XRenderComposite (dpy, PictOpSrc, blackPicture, None, rootPicture,
  1186. 0, 0, 0, 0, 0, 0, root_width, root_height);
  1187. #endif
  1188. #if DEBUG_REPAINT
  1189. printf ("paint:");
  1190. #endif
  1191. // Time delayed garbage collect
  1192. // It waits 10 seconds before destroying window data
  1193. // This allows the fade out to perform smoothly under all conditions
  1194. // Yes, this code is somewhat inefficient!
  1195. // But it shouldn't matter unless someone has tens of thousands of windows open...
  1196. // If the user can set a fade out that is longer than 10 seconds,
  1197. // then the value must be increased. I am assuming that 10 seconds
  1198. // is far too long for any normal human being to wait... ;-)
  1199. for (w = list; w; w = w->next)
  1200. {
  1201. if (w->destruct_requested) {
  1202. int curtime = get_time_in_milliseconds();
  1203. if ((curtime - w->destruct_request_time) > 10000) {
  1204. finish_destroy_win (dpy, w->id, True);
  1205. w = list;
  1206. }
  1207. }
  1208. }
  1209. for (w = list; w; w = w->next)
  1210. {
  1211. #if DEBUG_WINDOWS
  1212. window_count++;
  1213. #endif
  1214. #if CAN_DO_USABLE
  1215. if (!w->usable)
  1216. continue;
  1217. #endif
  1218. /* never painted, ignore it */
  1219. if ((!screen_damaged) && (!w->damaged))
  1220. continue;
  1221. /* skip invisible windows */
  1222. if (w->a.x + w->a.width < 1 || w->a.y + w->a.height < 1 || w->a.x >= root_width || w->a.y >= root_height)
  1223. continue;
  1224. if (!w->picture)
  1225. {
  1226. XRenderPictureAttributes pa;
  1227. XRenderPictFormat *format;
  1228. Drawable draw = w->id;
  1229. #if HAS_NAME_WINDOW_PIXMAP
  1230. if (hasNamePixmap && !w->pixmap)
  1231. w->pixmap = XCompositeNameWindowPixmap (dpy, w->id);
  1232. if (w->pixmap)
  1233. draw = w->pixmap;
  1234. #endif
  1235. format = sXRenderFindVisualFormat (dpy, w->a.visual);
  1236. pa.subwindow_mode = IncludeInferiors;
  1237. w->picture = XRenderCreatePicture (dpy, draw,
  1238. format,
  1239. CPSubwindowMode,
  1240. &pa);
  1241. }
  1242. #if DEBUG_REPAINT
  1243. printf (" 0x%x", w->id);
  1244. #endif
  1245. if (clipChanged)
  1246. {
  1247. if (w->borderSize)
  1248. {
  1249. set_ignore (dpy, NextRequest (dpy));
  1250. XFixesDestroyRegion (dpy, w->borderSize);
  1251. w->borderSize = None;
  1252. }
  1253. if (w->decoRegion)
  1254. {
  1255. set_ignore (dpy, NextRequest (dpy));
  1256. XFixesDestroyRegion (dpy, w->decoRegion);
  1257. w->decoRegion = None;
  1258. }
  1259. if (w->contentRegion)
  1260. {
  1261. set_ignore (dpy, NextRequest (dpy));
  1262. XFixesDestroyRegion (dpy, w->contentRegion);
  1263. w->contentRegion = None;
  1264. }
  1265. if (w->extents)
  1266. {
  1267. XFixesDestroyRegion (dpy, w->extents);
  1268. w->extents = None;
  1269. }
  1270. if (w->borderClip)
  1271. {
  1272. XFixesDestroyRegion (dpy, w->borderClip);
  1273. w->borderClip = None;
  1274. }
  1275. }
  1276. if (!w->borderSize)
  1277. w->borderSize = border_size (dpy, w);
  1278. if (!w->extents)
  1279. w->extents = win_extents (dpy, w);
  1280. if ((w->mode == WINDOW_SOLID) || ((w->mode == WINDOW_TRANS) && w->decoHash))
  1281. {
  1282. int x, y, wid, hei;
  1283. #if HAS_NAME_WINDOW_PIXMAP
  1284. x = w->a.x;
  1285. y = w->a.y;
  1286. wid = w->a.width + w->a.border_width * 2;
  1287. hei = w->a.height + w->a.border_width * 2;
  1288. #else
  1289. x = w->a.x + w->a.border_width;
  1290. y = w->a.y + w->a.border_width;
  1291. wid = w->a.width;
  1292. hei = w->a.height;
  1293. #endif
  1294. XFixesSetPictureClipRegion (dpy, rootBuffer, 0, 0, region);
  1295. set_ignore (dpy, NextRequest (dpy));
  1296. /*XFixesSubtractRegion (dpy, region, region, w->borderSize);
  1297. set_ignore (dpy, NextRequest (dpy));*/
  1298. if (w->mode == WINDOW_SOLID)
  1299. {
  1300. XFixesSubtractRegion (dpy, region, region, w->borderSize);
  1301. set_ignore (dpy, NextRequest (dpy));
  1302. XRenderComposite (dpy, PictOpSrc, w->picture, None, rootBuffer,
  1303. 0, 0, 0, 0, x, y, wid, hei);
  1304. if (w->dimPicture)
  1305. XRenderComposite (dpy, PictOpOver, w->dimPicture, None, rootBuffer, 0, 0, 0, 0, x, y, wid, hei);
  1306. }
  1307. else
  1308. {
  1309. if (!w->contentRegion)
  1310. w->contentRegion = content_region (dpy, w);
  1311. XFixesSubtractRegion (dpy, region, region, w->contentRegion);
  1312. set_ignore (dpy, NextRequest (dpy));
  1313. /*solid part*/
  1314. XRenderComposite (dpy, PictOpSrc, w->picture, None, rootBuffer,
  1315. _LEFTWIDTH_(w->decoHash), _TOPHEIGHT_(w->decoHash), 0, 0,
  1316. x + _LEFTWIDTH_(w->decoHash),
  1317. y + _TOPHEIGHT_(w->decoHash),
  1318. wid - _LEFTWIDTH_(w->decoHash) - _RIGHTWIDTH_(w->decoHash),
  1319. hei - _TOPHEIGHT_(w->decoHash) - _BOTTOMHEIGHT_(w->decoHash));
  1320. }
  1321. }
  1322. if (!w->borderClip)
  1323. {
  1324. w->borderClip = XFixesCreateRegion (dpy, 0, 0);
  1325. XFixesCopyRegion (dpy, w->borderClip, region);
  1326. }
  1327. w->prev_trans = t;
  1328. t = w;
  1329. }
  1330. #if DEBUG_WINDOWS
  1331. printf("window count: %d\n", window_count);
  1332. #endif
  1333. #if DEBUG_REPAINT
  1334. printf ("\n");
  1335. fflush (stdout);
  1336. #endif
  1337. XFixesSetPictureClipRegion (dpy, rootBuffer, 0, 0, region);
  1338. paint_root (dpy);
  1339. for (w = t; w; w = w->prev_trans)
  1340. {
  1341. if (w->shadowSize > 0){
  1342. if (winTypeShadow[w->windowType]) {
  1343. switch (compMode) {
  1344. case CompSimple:
  1345. break;
  1346. case CompServerShadows:
  1347. XFixesSetPictureClipRegion (dpy, rootBuffer, 0, 0, w->borderClip);
  1348. set_ignore (dpy, NextRequest (dpy));
  1349. if (w->opacity != OPAQUE && !w->shadowPict)
  1350. w->shadowPict = solid_picture (dpy, True,
  1351. (double) w->opacity / OPAQUE * 0.3,
  1352. 0, 0, 0);
  1353. XRenderComposite (dpy, PictOpOver,
  1354. w->shadowPict ? w->shadowPict : transBlackPicture,
  1355. w->picture, rootBuffer,
  1356. 0, 0, 0, 0,
  1357. w->a.x + w->shadow_dx,
  1358. w->a.y + w->shadow_dy,
  1359. w->shadow_width, w->shadow_height);
  1360. break;
  1361. case CompClientShadows:
  1362. if (w->shadow)
  1363. {
  1364. XFixesSetPictureClipRegion (dpy, rootBuffer, 0, 0, w->borderClip);
  1365. XRenderComposite (dpy, PictOpOver, blackPicture, w->shadow, rootBuffer,
  1366. 0, 0, 0, 0,
  1367. w->a.x + w->shadow_dx,
  1368. w->a.y + w->shadow_dy,
  1369. w->shadow_width, w->shadow_height);
  1370. }
  1371. break;
  1372. }
  1373. }
  1374. }
  1375. if (w->opacity != OPAQUE && !w->alphaPict)
  1376. w->alphaPict = solid_picture (dpy, False,
  1377. (double) w->opacity / OPAQUE, shadowColor.red, shadowColor.green, shadowColor.blue);
  1378. if (w->mode == WINDOW_TRANS)
  1379. {
  1380. int x, y, wid, hei;
  1381. XFixesIntersectRegion (dpy, w->borderClip, w->borderClip, w->borderSize);
  1382. XFixesSetPictureClipRegion (dpy, rootBuffer, 0, 0, w->borderClip);
  1383. #if HAS_NAME_WINDOW_PIXMAP
  1384. x = w->a.x;
  1385. y = w->a.y;
  1386. wid = w->a.width + w->a.border_width * 2;
  1387. hei = w->a.height + w->a.border_width * 2;
  1388. #else
  1389. x = w->a.x + w->a.border_width;
  1390. y = w->a.y + w->a.border_width;
  1391. wid = w->a.width;
  1392. hei = w->a.height;
  1393. #endif
  1394. set_ignore (dpy, NextRequest (dpy));
  1395. if (!w->decoHash)
  1396. {
  1397. XRenderComposite (dpy, PictOpOver, w->picture, w->alphaPict, rootBuffer,
  1398. 0, 0, 0, 0, x, y, wid, hei);
  1399. }
  1400. else
  1401. {
  1402. /*trans part*/
  1403. /* PICTURE ;)
  1404. |-----------------------------|
  1405. | top |
  1406. |-----------------------------|
  1407. |l | | r|
  1408. |e | | i|
  1409. |f | | g|
  1410. |t | | h|
  1411. |--------------------------| t|
  1412. | bottom | |
  1413. |--------------------------|--|*/
  1414. /*top*/
  1415. XRenderComposite (dpy, PictOpOver, w->picture, w->alphaPict, rootBuffer,
  1416. 0, 0, 0, 0, x, y, wid, _TOPHEIGHT_(w->decoHash));
  1417. /*right*/
  1418. XRenderComposite (dpy, PictOpOver, w->picture, w->alphaPict, rootBuffer,
  1419. wid - _RIGHTWIDTH_(w->decoHash), _TOPHEIGHT_(w->decoHash),
  1420. 0, 0,
  1421. x + wid - _RIGHTWIDTH_(w->decoHash),
  1422. y + _TOPHEIGHT_(w->decoHash), _RIGHTWIDTH_(w->decoHash),
  1423. hei - _TOPHEIGHT_(w->decoHash));
  1424. /*bottom*/
  1425. XRenderComposite (dpy, PictOpOver, w->picture, w->alphaPict, rootBuffer,
  1426. 0, hei - _BOTTOMHEIGHT_(w->decoHash), 0, 0,
  1427. x, y + hei - _BOTTOMHEIGHT_(w->decoHash),
  1428. wid - _RIGHTWIDTH_(w->decoHash), _BOTTOMHEIGHT_(w->decoHash));
  1429. /*left*/
  1430. XRenderComposite (dpy, PictOpOver, w->picture, w->alphaPict, rootBuffer,
  1431. 0, _TOPHEIGHT_(w->decoHash), 0, 0,
  1432. x, y + _TOPHEIGHT_(w->decoHash),
  1433. _LEFTWIDTH_(w->decoHash), hei - _TOPHEIGHT_(w->decoHash) - _BOTTOMHEIGHT_(w->decoHash));
  1434. }
  1435. }
  1436. else if (w->mode == WINDOW_ARGB)
  1437. {
  1438. int x, y, wid, hei;
  1439. XFixesIntersectRegion (dpy, w->borderClip, w->borderClip, w->borderSize);
  1440. XFixesSetPictureClipRegion (dpy, rootBuffer, 0, 0, w->borderClip);
  1441. #if HAS_NAME_WINDOW_PIXMAP
  1442. x = w->a.x;
  1443. y = w->a.y;
  1444. wid = w->a.width + w->a.border_width * 2;
  1445. hei = w->a.height + w->a.border_width * 2;
  1446. #else
  1447. x = w->a.x + w->a.border_width;
  1448. y = w->a.y + w->a.border_width;
  1449. wid = w->a.width;
  1450. hei = w->a.height;
  1451. #endif
  1452. set_ignore (dpy, NextRequest (dpy));
  1453. /* Here we redraw the background of the transparent window if we want
  1454. to do anything special (i.e. anything other than showing the
  1455. windows and desktop prestacked behind of the window).
  1456. For example, if you want to blur the background or show another
  1457. background pixmap entirely here is the place to do it; simply
  1458. draw the new background onto rootBuffer before continuing! */
  1459. if (w->isInFade == False) {
  1460. if (w->show_root_tile == True) {
  1461. XRenderComposite (dpy, PictOpSrc, rootTile, None, rootBuffer,
  1462. x, y, x, y,
  1463. x, y, wid, hei);
  1464. }
  1465. }
  1466. XRenderComposite (dpy, PictOpOver, w->picture, w->alphaPict, rootBuffer,
  1467. 0, 0, 0, 0,
  1468. x, y, wid, hei);
  1469. }
  1470. XFixesDestroyRegion (dpy, w->borderClip);
  1471. w->borderClip = None;
  1472. }
  1473. XFixesDestroyRegion (dpy, region);
  1474. if (rootBuffer != rootPicture)
  1475. {
  1476. #if 0
  1477. XTransform t;
  1478. t.matrix[0][0] = XDoubleToFixed (3.0 /*/ scale*/);
  1479. t.matrix[0][1] = 0.0;
  1480. t.matrix[0][2] = 0.0;
  1481. t.matrix[1][0] = 0.0;
  1482. t.matrix[1][1] = XDoubleToFixed (1.0 /*/ scale*/);
  1483. t.matrix[1][2] = 0.0;
  1484. t.matrix[2][0] = 0.0;
  1485. t.matrix[2][1] = 0.0;
  1486. t.matrix[2][2] = XDoubleToFixed (1.0);
  1487. XRenderSetPictureTransform (dpy, rootBuffer, &t);
  1488. #endif
  1489. XFixesSetPictureClipRegion (dpy, rootBuffer, 0, 0, None);
  1490. XRenderComposite (dpy, PictOpSrc, rootBuffer, None, rootPicture,
  1491. 0, 0, 0, 0, 0, 0, root_width, root_height);
  1492. }
  1493. screen_damaged = False;
  1494. }
  1495. static void
  1496. add_damage (Display *dpy, XserverRegion damage)
  1497. {
  1498. if (allDamage)
  1499. {
  1500. XFixesUnionRegion (dpy, allDamage, allDamage, damage);
  1501. XFixesDestroyRegion (dpy, damage);
  1502. }
  1503. else
  1504. allDamage = damage;
  1505. }
  1506. static void damage_win (Display *dpy, XDamageNotifyEvent *de);
  1507. static void
  1508. repair_win (Display *dpy, win *w)
  1509. {
  1510. XserverRegion parts;
  1511. if (!w->damaged)
  1512. {
  1513. parts = win_extents (dpy, w);
  1514. set_ignore (dpy, NextRequest (dpy));
  1515. XDamageSubtract (dpy, w->damage, None, None);
  1516. }
  1517. else
  1518. {
  1519. XserverRegion o;
  1520. parts = XFixesCreateRegion (dpy, 0, 0);
  1521. set_ignore (dpy, NextRequest (dpy));
  1522. XDamageSubtract (dpy, w->damage, None, parts);
  1523. XFixesTranslateRegion (dpy, parts,
  1524. w->a.x + w->a.border_width,
  1525. w->a.y + w->a.border_width);
  1526. if (compMode == CompServerShadows)
  1527. {
  1528. o = XFixesCreateRegion (dpy, 0, 0);
  1529. XFixesCopyRegion (dpy, o, parts);
  1530. XFixesTranslateRegion (dpy, o, w->shadow_dx, w->shadow_dy);
  1531. XFixesUnionRegion (dpy, parts, parts, o);
  1532. XFixesDestroyRegion (dpy, o);
  1533. }
  1534. }
  1535. add_damage (dpy, parts);
  1536. w->damaged = 1;
  1537. }
  1538. static const char*
  1539. wintype_name(wintype type)
  1540. {
  1541. const char *t;
  1542. switch (type) {
  1543. case WINTYPE_DESKTOP: t = "desktop"; break;
  1544. case WINTYPE_DOCK: t = "dock"; break;
  1545. case WINTYPE_TOOLBAR: t = "toolbar"; break;
  1546. case WINTYPE_MENU: t = "menu"; break;
  1547. case WINTYPE_UTILITY: t = "utility"; break;
  1548. case WINTYPE_SPLASH: t = "slash"; break;
  1549. case WINTYPE_DIALOG: t = "dialog"; break;
  1550. case WINTYPE_NORMAL: t = "normal"; break;
  1551. case WINTYPE_DROPDOWN_MENU: t = "dropdown"; break;
  1552. case WINTYPE_POPUP_MENU: t = "popup"; break;
  1553. case WINTYPE_TOOLTIP: t = "tooltip"; break;
  1554. case WINTYPE_NOTIFY: t = "notification"; break;
  1555. case WINTYPE_COMBO: t = "combo"; break;
  1556. case WINTYPE_DND: t = "dnd"; break;
  1557. default: t = "unknown"; break;
  1558. }
  1559. return t;
  1560. }
  1561. void repaint_root_overlay_window ()
  1562. {
  1563. XRectangle r;
  1564. r.x = 0;
  1565. r.y = 0;
  1566. r.width = root_width;
  1567. r.height = root_height;
  1568. XserverRegion region = XFixesCreateRegion (dpy, &r, 1);
  1569. add_damage (dpy, region);
  1570. }
  1571. static wintype
  1572. get_wintype_prop(Display * dpy, Window w)
  1573. {
  1574. Atom actual;
  1575. wintype ret;
  1576. int format;
  1577. unsigned long n, left, off;
  1578. unsigned char *data;
  1579. ret = (wintype)-1;
  1580. off = 0;
  1581. do {
  1582. set_ignore (dpy, NextRequest (dpy));
  1583. int result = XGetWindowProperty (dpy, w, winTypeAtom, off, 1L, False,
  1584. XA_ATOM, &actual, &format,
  1585. &n, &left, &data);
  1586. if (result != Success)
  1587. break;
  1588. if (data != None)
  1589. {
  1590. int i;
  1591. for (i = 0; i < NUM_WINTYPES; ++i) {
  1592. Atom a;
  1593. memcpy (&a, data, sizeof (Atom));
  1594. if (a == winType[i]) {
  1595. /* known type */
  1596. ret = i;
  1597. break;
  1598. }
  1599. }
  1600. XFree ( (void *) data);
  1601. }
  1602. ++off;
  1603. } while (left >= 4 && ret == (wintype)-1);
  1604. return ret;
  1605. }
  1606. static wintype
  1607. determine_wintype (Display *dpy, Window w, Window top)
  1608. {
  1609. Window root_return, parent_return;
  1610. Window *children = NULL;
  1611. unsigned int nchildren, i;
  1612. wintype type;
  1613. type = get_wintype_prop (dpy, w);
  1614. if (type != (wintype)-1)
  1615. return type;
  1616. set_ignore (dpy, NextRequest (dpy));
  1617. if (!XQueryTree (dpy, w, &root_return, &parent_return, &children,
  1618. &nchildren))
  1619. {
  1620. /* XQueryTree failed. */
  1621. if (children)
  1622. XFree ((void *)children);
  1623. return (wintype)-1;
  1624. }
  1625. for (i = 0;i < nchildren;i++)
  1626. {
  1627. type = determine_wintype (dpy, children[i], top);
  1628. if (type != (wintype)-1)
  1629. return type;
  1630. }
  1631. if (children)
  1632. XFree ((void *)children);
  1633. if (w != top)
  1634. return (wintype)-1;
  1635. else
  1636. return WINTYPE_NORMAL;
  1637. }
  1638. static unsigned int
  1639. get_opacity_prop(Display *dpy, win *w, unsigned int def);
  1640. static void
  1641. map_win (Display *dpy, Window id, unsigned long sequence, Bool fade)
  1642. {
  1643. win *w = find_win (dpy, id);
  1644. Drawable back;
  1645. if (!w)
  1646. return;
  1647. w->a.map_state = IsViewable;
  1648. /* This needs to be here or else we lose transparency messages */
  1649. XSelectInput (dpy, id, PropertyChangeMask);
  1650. /* This needs to be here since we don't get PropertyNotify when unmapped */
  1651. w->opacity = get_opacity_prop (dpy, w, OPAQUE);
  1652. determine_mode (dpy, w);
  1653. w->windowType = determine_wintype (dpy, w->id, w->id);
  1654. if ((w->windowType < 0) || (w->windowType > NUM_WINTYPES)) w->windowType = WINTYPE_NORMAL;
  1655. #if 0
  1656. printf("window 0x%x type %s\n", w->id, wintype_name(w->windowType));
  1657. #endif
  1658. #if CAN_DO_USABLE
  1659. w->damage_bounds.x = w->damage_bounds.y = 0;
  1660. w->damage_bounds.width = w->damage_bounds.height = 0;
  1661. #endif
  1662. w->damaged = 0;
  1663. #if WORK_AROUND_FGLRX
  1664. if (w->a.x != 0) {
  1665. XserverRegion extents = win_extents (dpy, w);
  1666. XDamageNotifyEvent de;
  1667. de.drawable = w->id;
  1668. de.area.x = 0;
  1669. de.area.y = 0;
  1670. de.area.width = w->a.width + w->a.border_width * 2;
  1671. de.area.height = w->a.height + w->a.border_width * 2;
  1672. damage_win(dpy, &de);
  1673. XFixesDestroyRegion (dpy, extents);
  1674. }
  1675. #endif
  1676. w->a_prev = w->a;
  1677. if (fade && winTypeFade[w->windowType])
  1678. set_fade (dpy, w, 0, get_opacity_prop(dpy, w, OPAQUE)*1.0/OPAQUE, fade_in_step, 0, False, True, True, True);
  1679. }
  1680. static void
  1681. finish_unmap_win (Display *dpy, win *w)
  1682. {
  1683. w->damaged = 0;
  1684. #if CAN_DO_USABLE
  1685. w->usable = False;
  1686. #endif
  1687. if (w->extents != None)
  1688. {
  1689. add_damage (dpy, w->extents); /* destroys region */
  1690. w->extents = None;
  1691. }
  1692. #if HAS_NAME_WINDOW_PIXMAP
  1693. if (w->pixmap)
  1694. {
  1695. XFreePixmap (dpy, w->pixmap);
  1696. w->pixmap = None;
  1697. }
  1698. #endif
  1699. if (w->picture)
  1700. {
  1701. set_ignore (dpy, NextRequest (dpy));
  1702. XRenderFreePicture (dpy, w->picture);
  1703. w->picture = None;
  1704. }
  1705. /* don't care about properties anymore */
  1706. set_ignore (dpy, NextRequest (dpy));
  1707. XSelectInput(dpy, w->id, 0);
  1708. if (w->borderSize)
  1709. {
  1710. set_ignore (dpy, NextRequest (dpy));
  1711. XFixesDestroyRegion (dpy, w->borderSize);
  1712. w->borderSize = None;
  1713. }
  1714. if (w->decoRegion)
  1715. {
  1716. set_ignore (dpy, NextRequest (dpy));
  1717. XFixesDestroyRegion (dpy, w->decoRegion);
  1718. w->decoRegion = None;
  1719. }
  1720. if (w->contentRegion)
  1721. {
  1722. set_ignore (dpy, NextRequest (dpy));
  1723. XFixesDestroyRegion (dpy, w->contentRegion);
  1724. w->contentRegion = None;
  1725. }
  1726. if (w->shadow)
  1727. {
  1728. XRenderFreePicture (dpy, w->shadow);
  1729. w->shadow = None;
  1730. }
  1731. if (w->borderClip)
  1732. {
  1733. XFixesDestroyRegion (dpy, w->borderClip);
  1734. w->borderClip = None;
  1735. }
  1736. clipChanged = True;
  1737. }
  1738. #if HAS_NAME_WINDOW_PIXMAP
  1739. static void
  1740. unmap_callback (Display *dpy, win *w, Bool gone)
  1741. {
  1742. finish_unmap_win (dpy, w);
  1743. }
  1744. #endif
  1745. static void
  1746. unmap_win (Display *dpy, Window id, Bool fade)
  1747. {
  1748. win *w = find_win (dpy, id);
  1749. if (!w)
  1750. return;
  1751. if (w->a.map_state != IsUnmapped) {
  1752. w->a.map_state = IsUnmapped;
  1753. #if HAS_NAME_WINDOW_PIXMAP
  1754. if (w->pixmap && fade && winTypeFade[w->windowType]) {
  1755. set_fade (dpy, w, w->opacity*1.0/OPAQUE, 0.0, fade_out_step, unmap_callback, False, False, True, True);
  1756. }
  1757. else
  1758. #endif
  1759. finish_unmap_win (dpy, w);
  1760. }
  1761. }
  1762. /* Get the opacity prop from window
  1763. not found: default
  1764. otherwise the value
  1765. */
  1766. static unsigned int
  1767. get_opacity_prop(Display *dpy, win *w, unsigned int def)
  1768. {
  1769. Atom actual;
  1770. int format;
  1771. unsigned long n, left;
  1772. unsigned char *data;
  1773. int result = XGetWindowProperty(dpy, w->id, opacityAtom, 0L, 1L, False,
  1774. XA_CARDINAL, &actual, &format,
  1775. &n, &left, &data);
  1776. if (result == Success && data != NULL && format == 32 )
  1777. {
  1778. unsigned int i;
  1779. i = *(long*)data;
  1780. XFree( (void *) data);
  1781. return i;
  1782. }
  1783. return def;
  1784. }
  1785. static unsigned int
  1786. get_shadow_prop(Display *dpy, win *w)
  1787. {
  1788. Atom actual;
  1789. int format;
  1790. unsigned long n, left;
  1791. unsigned char *data = NULL;
  1792. int result = XGetWindowProperty(dpy, w->id, shadowAtom, 0L, 1L, False,
  1793. XA_CARDINAL, &actual, &format,
  1794. &n, &left, &data);
  1795. if (result == Success && data != NULL && format == 32 )
  1796. {
  1797. unsigned int i;
  1798. i = *(long*)data;
  1799. XFree( (void *) data);
  1800. /*i added this for security reaons but limiting a value to 200% is somewhat indiscriminate
  1801. if (i > 200)
  1802. return 200;
  1803. else*/
  1804. return i;
  1805. }
  1806. return 100;
  1807. }
  1808. static unsigned int
  1809. get_shade_prop(Display *dpy, win *w)
  1810. {
  1811. Atom actual;
  1812. int format;
  1813. unsigned long n, left;
  1814. unsigned char *data = NULL;
  1815. int result = XGetWindowProperty(dpy, w->id, shadeAtom, 0L, 1L, False,
  1816. XA_CARDINAL, &actual, &format,
  1817. &n, &left, &data);
  1818. if (result == Success && data != NULL && format == 32 )
  1819. {
  1820. unsigned int i;
  1821. i = *(long*)data;
  1822. XFree( (void *) data);
  1823. return i;
  1824. }
  1825. return 0;
  1826. }
  1827. static Bool
  1828. get_shapable_prop(Display *dpy, win *w)
  1829. {
  1830. Atom actual;
  1831. int format;
  1832. unsigned long n, left;
  1833. unsigned char *data = NULL;
  1834. int result = XGetWindowProperty(dpy, w->id, shapableAtom, 0L, 1L, False,
  1835. XA_CARDINAL, &actual, &format,
  1836. &n, &left, &data);
  1837. if (result == Success && data != NULL && format == 32 )
  1838. {
  1839. unsigned int i;
  1840. i = *(long*)data;
  1841. XFree( (void *) data);
  1842. return i==1;
  1843. }
  1844. return True; /*in general, the window should be shapable*/
  1845. }
  1846. static unsigned int
  1847. get_decoHash_prop(Display *dpy, win *w)
  1848. {
  1849. Atom actual;
  1850. int format;
  1851. unsigned long n, left;
  1852. unsigned char *data = NULL;
  1853. int result = XGetWindowProperty(dpy, w->id, decoHashAtom, 0L, 1L, False,
  1854. XA_CARDINAL, &actual, &format,
  1855. &n, &left, &data);
  1856. if (result == Success && data != NULL && format == 32 )
  1857. {
  1858. unsigned int i;
  1859. i = *(long*)data;
  1860. XFree( (void *) data);
  1861. return i;
  1862. }
  1863. return 0; /*no titlebar*/
  1864. }
  1865. static unsigned int
  1866. get_dim_prop(Display *dpy, win *w)
  1867. {
  1868. Atom actual;
  1869. int format;
  1870. unsigned long n, left;
  1871. unsigned char *data = NULL;
  1872. int result = XGetWindowProperty(dpy, w->id, dimAtom, 0L, 1L, False,
  1873. XA_CARDINAL, &actual, &format,
  1874. &n, &left, &data);
  1875. if (result == Success && data != NULL)
  1876. {
  1877. unsigned int i;
  1878. memcpy (&i, data, sizeof (unsigned int));
  1879. XFree( (void *) data);
  1880. if (i == 0) i = 1;
  1881. return i;
  1882. }
  1883. return OPAQUE; /*in general, the window is not dimmed*/
  1884. }
  1885. static unsigned int
  1886. get_deskchange_prop(Display *dpy, Window id)
  1887. {
  1888. Atom actual;
  1889. int format;
  1890. unsigned long n, left;
  1891. unsigned char *data = NULL;
  1892. int result = XGetWindowProperty(dpy, id, deskChangeAtom, 0L, 1L, False,
  1893. XA_CARDINAL, &actual, &format,
  1894. &n, &left, &data);
  1895. if (result == Success && data != NULL)
  1896. {
  1897. unsigned int i;
  1898. memcpy (&i, data, sizeof (unsigned int));
  1899. XFree( (void *) data);
  1900. if (i < 3)
  1901. return i;
  1902. }
  1903. return 0; /*no valid change state*/
  1904. }
  1905. /* Get the opacity property from the window in a percent format
  1906. not found: default
  1907. otherwise: the value
  1908. */
  1909. static double
  1910. get_opacity_percent(Display *dpy, win *w)
  1911. {
  1912. if (w && w->isInFade)
  1913. {
  1914. fade *f = find_fade(w);
  1915. return f->finish;
  1916. }
  1917. else
  1918. {
  1919. double def = winTypeOpacity[w->windowType];
  1920. unsigned int opacity = get_opacity_prop (dpy, w, (unsigned int)(OPAQUE*def));
  1921. return opacity*1.0/OPAQUE;
  1922. }
  1923. }
  1924. #if 0
  1925. static void
  1926. damage_shape(Display *dpy, win *w, XRectangle *shape_damage)
  1927. {
  1928. set_ignore (dpy, NextRequest (dpy));
  1929. XserverRegion region = XFixesCreateRegion (dpy, shape_damage, 1);
  1930. set_ignore (dpy, NextRequest (dpy));
  1931. XserverRegion tmpRegion;
  1932. add_damage(dpy, region);
  1933. win *i;
  1934. XRectangle *rect;
  1935. int n;
  1936. for (i = w; i; i = i->next)
  1937. {
  1938. XFixesIntersectRegion (dpy, tmpRegion, region, w->extents);
  1939. rect = XFixesFetchRegion (dpy, region, &n);
  1940. free(rect);
  1941. printf("%d\n",n);
  1942. if (n != 1)
  1943. {
  1944. w->damage = True;
  1945. XFixesSubtractRegion (dpy, region, region, w->extents);
  1946. }
  1947. else
  1948. break;
  1949. }
  1950. set_ignore (dpy, NextRequest (dpy));
  1951. XFixesDestroyRegion (dpy, tmpRegion);
  1952. set_ignore (dpy, NextRequest (dpy));
  1953. XFixesDestroyRegion (dpy, region);
  1954. }
  1955. #endif
  1956. static Bool
  1957. get_window_transparent_to_desktop(Display * dpy, Window w)
  1958. {
  1959. Atom actual;
  1960. int format;
  1961. unsigned long n, left;
  1962. unsigned char *data;
  1963. int result = XGetWindowProperty (dpy, w, winTDETTDAtom, 0L, 1L, False,
  1964. XA_ATOM, &actual, &format,
  1965. &n, &left, &data);
  1966. if (result == Success && data != None && format == 32 )
  1967. {
  1968. Atom a;
  1969. a = *(long*)data;
  1970. XFree ( (void *) data);
  1971. return True;
  1972. }
  1973. return False;
  1974. }
  1975. static void
  1976. determine_mode(Display *dpy, win *w)
  1977. {
  1978. int mode;
  1979. XRenderPictFormat *format;
  1980. unsigned int default_opacity;
  1981. /* if trans prop == -1 fall back on previous tests*/
  1982. if (w->alphaPict)
  1983. {
  1984. XRenderFreePicture (dpy, w->alphaPict);
  1985. w->alphaPict = None;
  1986. }
  1987. if (w->shadowPict)
  1988. {
  1989. XRenderFreePicture (dpy, w->shadowPict);
  1990. w->shadowPict = None;
  1991. }
  1992. if (w->a.class == InputOnly)
  1993. {
  1994. format = 0;
  1995. }
  1996. else
  1997. {
  1998. format = XRenderFindVisualFormat (dpy, w->a.visual);
  1999. }
  2000. if (!disable_argb && format && format->type == PictTypeDirect && format->direct.alphaMask)
  2001. {
  2002. mode = WINDOW_ARGB;
  2003. }
  2004. else if (w->opacity != OPAQUE)
  2005. {
  2006. mode = WINDOW_TRANS;
  2007. }
  2008. else
  2009. {
  2010. mode = WINDOW_SOLID;
  2011. }
  2012. w->mode = mode;
  2013. if (w->extents)
  2014. {
  2015. XserverRegion damage;
  2016. damage = XFixesCreateRegion (dpy, 0, 0);
  2017. XFixesCopyRegion (dpy, damage, w->extents);
  2018. add_damage (dpy, damage);
  2019. }
  2020. }
  2021. static Bool
  2022. determine_window_transparent_to_desktop (Display *dpy, Window w)
  2023. {
  2024. Window root_return, parent_return;
  2025. Window *children = NULL;
  2026. unsigned int nchildren, i;
  2027. Bool type;
  2028. type = get_window_transparent_to_desktop (dpy, w);
  2029. if (type == True)
  2030. return True;
  2031. if (!XQueryTree (dpy, w, &root_return, &parent_return, &children,
  2032. &nchildren))
  2033. {
  2034. /* XQueryTree failed. */
  2035. if (children)
  2036. XFree ((void *)children);
  2037. return False;
  2038. }
  2039. for (i = 0;i < nchildren;i++)
  2040. {
  2041. type = determine_window_transparent_to_desktop (dpy, children[i]);
  2042. if (type == True)
  2043. return True;
  2044. }
  2045. if (children)
  2046. XFree ((void *)children);
  2047. return False;
  2048. }
  2049. static void
  2050. add_win (Display *dpy, Window id, Window prev)
  2051. {
  2052. win *new = malloc (sizeof (win));
  2053. win **p;
  2054. unsigned int tmp;
  2055. if (!new)
  2056. return;
  2057. if (prev)
  2058. {
  2059. for (p = &list; *p; p = &(*p)->next)
  2060. if ((*p)->id == prev && !(*p)->destroyed)
  2061. break;
  2062. }
  2063. else
  2064. p = &list;
  2065. new->id = id;
  2066. set_ignore (dpy, NextRequest (dpy));
  2067. if (!XGetWindowAttributes (dpy, id, &new->a))
  2068. {
  2069. free (new);
  2070. return;
  2071. }
  2072. new->shaped = False;
  2073. new->shape_bounds.x = new->a.x;
  2074. new->shape_bounds.y = new->a.y;
  2075. new->shape_bounds_prev = new->shape_bounds;
  2076. new->shape_bounds.width = new->a.width;
  2077. new->shape_bounds.height = new->a.height;
  2078. new->a_prev = new->a;
  2079. new->damaged = 0;
  2080. #if CAN_DO_USABLE
  2081. new->usable = False;
  2082. #endif
  2083. #if HAS_NAME_WINDOW_PIXMAP
  2084. new->pixmap = None;
  2085. #endif
  2086. new->picture = None;
  2087. if (new->a.class == InputOnly)
  2088. {
  2089. new->damage_sequence = 0;
  2090. new->damage = None;
  2091. }
  2092. else
  2093. {
  2094. new->damage_sequence = NextRequest (dpy);
  2095. new->damage = XDamageCreate (dpy, id, XDamageReportNonEmpty);
  2096. XShapeSelectInput (dpy, id, ShapeNotifyMask);
  2097. }
  2098. new->isInFade = False;
  2099. new->alphaPict = None;
  2100. new->shadowPict = None;
  2101. new->borderSize = None;
  2102. new->decoRegion = None;
  2103. new->contentRegion = None;
  2104. new->extents = None;
  2105. new->shadow = None;
  2106. new->shadow_dx = 0;
  2107. new->shadow_dy = 0;
  2108. new->shadow_width = 0;
  2109. new->shadow_height = 0;
  2110. new->opacity = OPAQUE;
  2111. new->destroyed = False;
  2112. new->destruct_queued = False;
  2113. new->destruct_requested = False;
  2114. new->destruct_request_time = 0;
  2115. new->shadowSize = 100;
  2116. new->decoHash = 0;
  2117. new->show_root_tile = determine_window_transparent_to_desktop(dpy, id);
  2118. new->windowType = determine_wintype (dpy, new->id, new->id);
  2119. if ((new->windowType < 0) || (new->windowType > NUM_WINTYPES)) new->windowType = WINTYPE_NORMAL;
  2120. new->borderClip = None;
  2121. new->prev_trans = 0;
  2122. XShapeSelectInput( dpy, id, ShapeNotifyMask );
  2123. new->shadowSize = get_shadow_prop (dpy, new);
  2124. new->shapable = get_shapable_prop(dpy, new);
  2125. new->decoHash = get_decoHash_prop(dpy, new);
  2126. tmp = get_dim_prop(dpy, new);
  2127. new->dimPicture = (tmp < OPAQUE) ? solid_picture (dpy, True, (double)tmp/OPAQUE, 0.1, 0.1, 0.1) : None;
  2128. new->next = *p;
  2129. *p = new;
  2130. if (new->a.map_state == IsViewable)
  2131. map_win (dpy, id, new->damage_sequence - 1, True);
  2132. }
  2133. void
  2134. restack_win (Display *dpy, win *w, Window new_above)
  2135. {
  2136. Window old_above;
  2137. if (w->next)
  2138. old_above = w->next->id;
  2139. else
  2140. old_above = None;
  2141. if (old_above != new_above)
  2142. {
  2143. win **prev;
  2144. /* unhook */
  2145. for (prev = &list; *prev; prev = &(*prev)->next)
  2146. if ((*prev) == w)
  2147. break;
  2148. *prev = w->next;
  2149. /* rehook */
  2150. for (prev = &list; *prev; prev = &(*prev)->next)
  2151. {
  2152. if ((!(*prev)->destroyed) && ((*prev)->id == new_above))
  2153. break;
  2154. }
  2155. w->next = *prev;
  2156. *prev = w;
  2157. }
  2158. }
  2159. static void
  2160. configure_win (Display *dpy, XConfigureEvent *ce)
  2161. {
  2162. win *w = find_win (dpy, ce->window);
  2163. Window above;
  2164. XserverRegion damage = None;
  2165. if (!w)
  2166. {
  2167. if (ce->window == root)
  2168. {
  2169. if (rootBuffer)
  2170. {
  2171. XRenderFreePicture (dpy, rootBuffer);
  2172. rootBuffer = None;
  2173. }
  2174. root_width = ce->width;
  2175. root_height = ce->height;
  2176. }
  2177. return;
  2178. }
  2179. #if CAN_DO_USABLE
  2180. if (w->usable)
  2181. #endif
  2182. {
  2183. damage = XFixesCreateRegion (dpy, 0, 0);
  2184. if (w->extents != None)
  2185. XFixesCopyRegion (dpy, damage, w->extents);
  2186. }
  2187. w->shape_bounds.x -= w->a.x;
  2188. w->shape_bounds.y -= w->a.y;
  2189. w->a.x = ce->x;
  2190. w->a.y = ce->y;
  2191. /* Only destroy the pixmap if the window is mapped */
  2192. if (w->a.map_state != IsUnmapped &&
  2193. (w->a.width != ce->width || w->a.height != ce->height))
  2194. {
  2195. #if HAS_NAME_WINDOW_PIXMAP
  2196. if (w->pixmap)
  2197. {
  2198. XFreePixmap (dpy, w->pixmap);
  2199. w->pixmap = None;
  2200. if (w->picture)
  2201. {
  2202. XRenderFreePicture (dpy, w->picture);
  2203. w->picture = None;
  2204. }
  2205. }
  2206. #endif
  2207. if (w->shadow)
  2208. {
  2209. XRenderFreePicture (dpy, w->shadow);
  2210. w->shadow = None;
  2211. }
  2212. }
  2213. w->a.width = ce->width;
  2214. w->a.height = ce->height;
  2215. w->a.border_width = ce->border_width;
  2216. w->a.override_redirect = ce->override_redirect;
  2217. restack_win (dpy, w, ce->above);
  2218. if (w->a.map_state != IsUnmapped && damage)
  2219. {
  2220. XserverRegion extents = win_extents (dpy, w);
  2221. XFixesUnionRegion (dpy, damage, damage, extents);
  2222. XFixesDestroyRegion (dpy, extents);
  2223. add_damage (dpy, damage);
  2224. }
  2225. w->shape_bounds.x += w->a.x;
  2226. w->shape_bounds.y += w->a.y;
  2227. if (!w->shaped)
  2228. {
  2229. w->shape_bounds.width = w->a.width;
  2230. w->shape_bounds.height = w->a.height;
  2231. }
  2232. if (w->a.map_state != IsUnmapped)
  2233. clipChanged = True;
  2234. }
  2235. static void
  2236. circulate_win (Display *dpy, XCirculateEvent *ce)
  2237. {
  2238. win *w = find_win (dpy, ce->window);
  2239. Window new_above;
  2240. if (!w)
  2241. return;
  2242. if (ce->place == PlaceOnTop)
  2243. new_above = list->id;
  2244. else
  2245. new_above = None;
  2246. restack_win (dpy, w, new_above);
  2247. clipChanged = True;
  2248. }
  2249. static void
  2250. finish_destroy_win (Display *dpy, Window id, Bool gone)
  2251. {
  2252. win **prev, *w;
  2253. for (prev = &list; (w = *prev); prev = &w->next)
  2254. if (w->id == id && w->destroyed)
  2255. {
  2256. if (gone)
  2257. finish_unmap_win (dpy, w);
  2258. *prev = w->next;
  2259. if (w->picture)
  2260. {
  2261. set_ignore (dpy, NextRequest (dpy));
  2262. XRenderFreePicture (dpy, w->picture);
  2263. w->picture = None;
  2264. }
  2265. if (w->alphaPict)
  2266. {
  2267. XRenderFreePicture (dpy, w->alphaPict);
  2268. w->alphaPict = None;
  2269. }
  2270. if (w->shadowPict)
  2271. {
  2272. XRenderFreePicture (dpy, w->shadowPict);
  2273. w->shadowPict = None;
  2274. }
  2275. if (w->shadow)
  2276. {
  2277. XRenderFreePicture (dpy, w->shadow);
  2278. w->shadow = None;
  2279. }
  2280. if (w->damage != None)
  2281. {
  2282. set_ignore (dpy, NextRequest (dpy));
  2283. XDamageDestroy (dpy, w->damage);
  2284. w->damage = None;
  2285. }
  2286. cleanup_fade (dpy, w);
  2287. free (w);
  2288. break;
  2289. }
  2290. }
  2291. #if HAS_NAME_WINDOW_PIXMAP
  2292. static void
  2293. destroy_callback (Display *dpy, win *w, Bool gone)
  2294. {
  2295. finish_destroy_win (dpy, w->id, gone);
  2296. }
  2297. #endif
  2298. static void
  2299. destroy_win (Display *dpy, Window id, Bool gone, Bool fadeout)
  2300. {
  2301. fade *f;
  2302. win *w = find_win (dpy, id);
  2303. if (w && w->destruct_queued == False) {
  2304. f = find_fade (w);
  2305. if (f) {
  2306. w->destruct_queued = True;
  2307. f->callback = destroy_callback;
  2308. w->destroyed = True;
  2309. }
  2310. else {
  2311. w->destroyed = True;
  2312. #if HAS_NAME_WINDOW_PIXMAP
  2313. if (w->pixmap && fadeout && winTypeFade[w->windowType]) {
  2314. set_fade (dpy, w, w->opacity*1.0/OPAQUE, 0.0, fade_out_step, destroy_callback, gone, False, True, True);
  2315. }
  2316. else
  2317. #endif
  2318. {
  2319. if (!gone) {
  2320. finish_destroy_win (dpy, id, gone);
  2321. }
  2322. else {
  2323. w->destruct_queued = True;
  2324. w->destruct_requested = True;
  2325. w->destruct_request_time = get_time_in_milliseconds();
  2326. }
  2327. }
  2328. }
  2329. }
  2330. }
  2331. /*
  2332. static void
  2333. dump_win (win *w)
  2334. {
  2335. printf ("\t%08lx: %d x %d + %d + %d (%d)\n", w->id,
  2336. w->a.width, w->a.height, w->a.x, w->a.y, w->a.border_width);
  2337. }
  2338. static void
  2339. dump_wins (void)
  2340. {
  2341. win *w;
  2342. printf ("windows:\n");
  2343. for (w = list; w; w = w->next)
  2344. dump_win (w);
  2345. }
  2346. */
  2347. static void
  2348. damage_win (Display *dpy, XDamageNotifyEvent *de)
  2349. {
  2350. win *w = find_win (dpy, de->drawable);
  2351. if (!w)
  2352. return;
  2353. #if WORK_AROUND_FGLRX
  2354. if (w->a.map_state != IsViewable)
  2355. return;
  2356. #endif
  2357. #if CAN_DO_USABLE
  2358. if (!w->usable)
  2359. {
  2360. if (w->damage_bounds.width == 0 || w->damage_bounds.height == 0)
  2361. {
  2362. w->damage_bounds = de->area;
  2363. }
  2364. else
  2365. {
  2366. if (de->area.x < w->damage_bounds.x)
  2367. {
  2368. w->damage_bounds.width += (w->damage_bounds.x - de->area.x);
  2369. w->damage_bounds.x = de->area.x;
  2370. }
  2371. if (de->area.y < w->damage_bounds.y)
  2372. {
  2373. w->damage_bounds.height += (w->damage_bounds.y - de->area.y);
  2374. w->damage_bounds.y = de->area.y;
  2375. }
  2376. if (de->area.x + de->area.width > w->damage_bounds.x + w->damage_bounds.width)
  2377. w->damage_bounds.width = de->area.x + de->area.width - w->damage_bounds.x;
  2378. if (de->area.y + de->area.height > w->damage_bounds.y + w->damage_bounds.height)
  2379. w->damage_bounds.height = de->area.y + de->area.height - w->damage_bounds.y;
  2380. }
  2381. #if 0
  2382. printf ("unusable damage [%d] %d, %d: %d x %d bounds %d, %d: %d x %d\n",
  2383. de->drawable,
  2384. de->area.x,
  2385. de->area.y,
  2386. de->area.width,
  2387. de->area.height,
  2388. w->damage_bounds.x,
  2389. w->damage_bounds.y,
  2390. w->damage_bounds.width,
  2391. w->damage_bounds.height);
  2392. #endif
  2393. if (w->damage_bounds.x <= 0 &&
  2394. w->damage_bounds.y <= 0 &&
  2395. w->a.width <= w->damage_bounds.x + w->damage_bounds.width &&
  2396. w->a.height <= w->damage_bounds.y + w->damage_bounds.height)
  2397. {
  2398. clipChanged = True;
  2399. if (winTypeFade[w->windowType]) {
  2400. set_fade (dpy, w, 0, get_opacity_percent (dpy, w), fade_in_step, 0, False, True, True, False);
  2401. }
  2402. w->usable = True;
  2403. }
  2404. }
  2405. if (w->usable)
  2406. #endif
  2407. repair_win (dpy, w);
  2408. }
  2409. static const char *
  2410. shape_kind(int kind)
  2411. {
  2412. static char buf[128];
  2413. switch(kind){
  2414. case ShapeBounding:
  2415. return "ShapeBounding";
  2416. case ShapeClip:
  2417. return "ShapeClip";
  2418. case ShapeInput:
  2419. return "ShapeInput";
  2420. default:
  2421. sprintf (buf, "Shape %d", kind);
  2422. return buf;
  2423. }
  2424. }
  2425. static void
  2426. shape_win (Display *dpy, XShapeEvent *se)
  2427. {
  2428. win *w = find_win (dpy, se->window);
  2429. if (!w)
  2430. return;
  2431. if (w->a.map_state == IsUnmapped)
  2432. return;
  2433. if (w->isInFade)
  2434. return;
  2435. if (se->kind == ShapeClip || se->kind == ShapeBounding)
  2436. {
  2437. XserverRegion region0;
  2438. XserverRegion region1;
  2439. #if 0
  2440. printf("win 0x%lx %s:%s %ux%u+%d+%d (@%d+%d)\n",
  2441. (unsigned long) se->window,
  2442. shape_kind(se->kind),
  2443. (se->shaped == True) ? "true" : "false",
  2444. se->width, se->height,
  2445. se->x, se->y,
  2446. w->a.x, w->a.y);
  2447. printf("\told %s %d+%d (@%d+%d)\n",
  2448. (w->shaped == True) ? "true" : "false",
  2449. w->shape_bounds_prev.width, w->shape_bounds_prev.height,
  2450. w->shape_bounds_prev.x, w->shape_bounds_prev.y);
  2451. #endif
  2452. clipChanged = True;
  2453. region0 = XFixesCreateRegion (dpy, &w->shape_bounds_prev, 1);
  2454. if (se->shaped == True)
  2455. {
  2456. w->shaped = True;
  2457. w->shape_bounds.x = w->a.x + se->x;
  2458. w->shape_bounds.y = w->a.y + se->y;
  2459. w->shape_bounds.width = se->width;
  2460. w->shape_bounds.height = se->height;
  2461. }
  2462. else
  2463. {
  2464. w->shaped = False;
  2465. w->shape_bounds.x = w->a.x;
  2466. w->shape_bounds.y = w->a.y;
  2467. w->shape_bounds.width = w->a.width;
  2468. w->shape_bounds.height = w->a.height;
  2469. }
  2470. region1 = XFixesCreateRegion (dpy, &w->shape_bounds, 1);
  2471. XFixesUnionRegion (dpy, region0, region0, region1);
  2472. XFixesDestroyRegion (dpy, region1);
  2473. /* ask for repaint of the old and new region */
  2474. paint_all (dpy, region0);
  2475. }
  2476. w->shape_bounds_prev = w->shape_bounds;
  2477. }
  2478. static void
  2479. damage_screen (Display *dpy)
  2480. {
  2481. XserverRegion region;
  2482. XRectangle r;
  2483. r.x = 0;
  2484. r.y = 0;
  2485. r.width = root_width;
  2486. r.height = root_height;
  2487. region = XFixesCreateRegion (dpy, &r, 1);
  2488. add_damage (dpy, region);
  2489. screen_damaged = True;
  2490. }
  2491. static int
  2492. error (Display *dpy, XErrorEvent *ev)
  2493. {
  2494. int o;
  2495. char *name = 0;
  2496. if (should_ignore (dpy, ev->serial))
  2497. return 0;
  2498. if (ev->request_code == composite_opcode &&
  2499. ev->minor_code == X_CompositeRedirectSubwindows)
  2500. {
  2501. fprintf (stderr, "Another composite manager is already running\n");
  2502. my_exit_code=2;
  2503. exit (2);
  2504. }
  2505. o = ev->error_code - xfixes_error;
  2506. switch (o) {
  2507. case BadRegion: name = "BadRegion"; break;
  2508. default: break;
  2509. }
  2510. o = ev->error_code - damage_error;
  2511. switch (o) {
  2512. case BadDamage: name = "BadDamage"; break;
  2513. default: break;
  2514. }
  2515. o = ev->error_code - render_error;
  2516. switch (o) {
  2517. case BadPictFormat: name ="BadPictFormat"; break;
  2518. case BadPicture: name ="BadPicture"; break;
  2519. case BadPictOp: name ="BadPictOp"; break;
  2520. case BadGlyphSet: name ="BadGlyphSet"; break;
  2521. case BadGlyph: name ="BadGlyph"; break;
  2522. default: break;
  2523. }
  2524. #ifndef NDEBUG
  2525. fprintf (stderr,"error %d request %d minor %d serial %d\n",
  2526. ev->error_code, ev->request_code, ev->minor_code, ev->serial);
  2527. #endif
  2528. /* abort (); this is just annoying to most people */
  2529. return 0;
  2530. }
  2531. static void
  2532. expose_root (Display *dpy, Window root, XRectangle *rects, int nrects)
  2533. {
  2534. XserverRegion region = XFixesCreateRegion (dpy, rects, nrects);
  2535. add_damage (dpy, region);
  2536. }
  2537. static int
  2538. ev_serial (XEvent *ev)
  2539. {
  2540. if ((ev->type & 0x7f) != KeymapNotify)
  2541. return ev->xany.serial;
  2542. return NextRequest (ev->xany.display);
  2543. }
  2544. static char *
  2545. ev_name (XEvent *ev)
  2546. {
  2547. static char buf[128];
  2548. switch (ev->type & 0x7f) {
  2549. case Expose:
  2550. return "Expose";
  2551. case MapNotify:
  2552. return "Map";
  2553. case UnmapNotify:
  2554. return "Unmap";
  2555. case ReparentNotify:
  2556. return "Reparent";
  2557. case CirculateNotify:
  2558. return "Circulate";
  2559. default:
  2560. if (ev->type == damage_event + XDamageNotify) {
  2561. return "Damage";
  2562. }
  2563. else if (ev->type == xshape_event + ShapeNotify)
  2564. {
  2565. return "Shape";
  2566. }
  2567. sprintf (buf, "Event %d", ev->type);
  2568. return buf;
  2569. }
  2570. }
  2571. static Window
  2572. ev_window (XEvent *ev)
  2573. {
  2574. switch (ev->type) {
  2575. case Expose:
  2576. return ev->xexpose.window;
  2577. case MapNotify:
  2578. return ev->xmap.window;
  2579. case UnmapNotify:
  2580. return ev->xunmap.window;
  2581. case ReparentNotify:
  2582. return ev->xreparent.window;
  2583. case CirculateNotify:
  2584. return ev->xcirculate.window;
  2585. default:
  2586. if (ev->type == damage_event + XDamageNotify) {
  2587. // fprintf(stderr, "%d", ev->type);
  2588. return ((XDamageNotifyEvent *) ev)->drawable;
  2589. }
  2590. else if (ev->type == xshape_event + ShapeNotify)
  2591. {
  2592. // fprintf(stderr, "%d", ev->type);
  2593. return ((XShapeEvent *) ev)->window;
  2594. }
  2595. return 0;
  2596. }
  2597. }
  2598. void
  2599. setShadowColor(char *value){ /*format nach #xxxxxx (html) �ndern?*/
  2600. unsigned int tmp;
  2601. char **res = NULL;
  2602. tmp = strtoul(value, res, 16);
  2603. if( !value || strlen(value) < 6 || strlen(value) > 8 || (*(value+1) == 'x' && strlen(value) < 8) || res != NULL ){
  2604. shadowColor.red = 0;
  2605. shadowColor.green = 0;
  2606. shadowColor.blue = 0;
  2607. printf("wrong hexadecimal (use 0xXXXXXX or XXXXXX)! defaulting to black...\n");
  2608. return;
  2609. }
  2610. shadowColor.blue = tmp&0xff;
  2611. tmp >>= 8;
  2612. shadowColor.green = tmp&0xff;
  2613. tmp >>= 8;
  2614. shadowColor.red = tmp&0xff;
  2615. }
  2616. typedef enum _option{
  2617. Display_=0,
  2618. Compmode,
  2619. ExcludeDockShadows,
  2620. FadeWindows,
  2621. FadeTrans,
  2622. AutoRedirect,
  2623. Synchronize,
  2624. ShadowColor,
  2625. ShadowRadius,
  2626. ShadowOpacity,
  2627. ShadowOffsetX,
  2628. ShadowOffsetY,
  2629. FadeOutStep,
  2630. FadeInStep,
  2631. FadeDelta,
  2632. DisableARGB,
  2633. FadeMenuWindows,
  2634. NUMBEROFOPTIONS
  2635. } Option;
  2636. const char *
  2637. options[NUMBEROFOPTIONS] = {
  2638. "Display", /*0*/
  2639. "Compmode", /*1*/
  2640. "ExcludeDockShadows", /*2*/
  2641. "FadeWindows", /*3*/
  2642. "FadeTrans", /*4*/
  2643. "AutoRedirect", /*5*/
  2644. "Synchronize", /*6*/
  2645. "ShadowColor", /*7*/
  2646. "ShadowRadius", /*8*/
  2647. "ShadowOpacity", /*9*/
  2648. "ShadowOffsetX", /*10*/
  2649. "ShadowOffsetY", /*11*/
  2650. "FadeOutStep", /*12*/
  2651. "FadeInStep", /*13*/
  2652. "FadeDelta", /*14*/
  2653. "DisableARGB", /*15*/
  2654. "FadeMenuWindows", /*16*/
  2655. /*put your thingy in here...*/
  2656. };
  2657. void
  2658. setValue(Option option, char *value ){
  2659. int i;
  2660. switch(option){ /*please keep that upside-down, because this way adding a new option is easier (all in one view)*/
  2661. case FadeDelta:
  2662. fade_delta = atoi(value);
  2663. if (fade_delta < 1)
  2664. fade_delta = 10;
  2665. break;
  2666. case FadeInStep:
  2667. fade_in_step = atof(value);
  2668. if (fade_in_step <= 0)
  2669. fade_in_step = 0.01;
  2670. break;
  2671. case FadeOutStep:
  2672. fade_out_step = atof(value);
  2673. if (fade_out_step <= 0)
  2674. fade_out_step = 0.01;
  2675. break;
  2676. case ShadowOffsetY:
  2677. shadowOffsetY = atoi(value);
  2678. break;
  2679. case ShadowOffsetX:
  2680. shadowOffsetX = atoi(value);
  2681. break;
  2682. case ShadowOpacity:
  2683. shadowOpacity = atof(value);
  2684. break;
  2685. case ShadowRadius:
  2686. shadowRadius = atoi(value);
  2687. break;
  2688. case ShadowColor:
  2689. setShadowColor(value);
  2690. break;
  2691. case Synchronize:
  2692. synchronize = ( strcasecmp(value, "true") == 0 );
  2693. break;
  2694. case AutoRedirect:
  2695. autoRedirect = ( strcasecmp(value, "true") == 0 );
  2696. break;
  2697. case FadeTrans:
  2698. fadeTrans = ( strcasecmp(value, "true") == 0 );
  2699. break;
  2700. case FadeWindows:
  2701. if ( strcasecmp(value, "true") == 0 ) {
  2702. int i;
  2703. for (i = 0; i < NUM_WINTYPES; ++i) {
  2704. if (i != WINTYPE_POPUP_MENU)
  2705. winTypeFade[i] = True;
  2706. }
  2707. }
  2708. break;
  2709. case FadeMenuWindows:
  2710. if ( strcasecmp(value, "true") == 0 ) {
  2711. winTypeFade[WINTYPE_POPUP_MENU] = True;
  2712. }
  2713. break;
  2714. case ExcludeDockShadows:
  2715. if ( strcasecmp(value, "true") == 0 ) {
  2716. winTypeShadow[WINTYPE_DOCK] = False;
  2717. }
  2718. break;
  2719. case Compmode:
  2720. if( strcasecmp(value, "CompClientShadows") == 0 ){
  2721. compMode = CompClientShadows;
  2722. for (i = 0; i < NUM_WINTYPES; ++i)
  2723. winTypeShadow[i] = True;
  2724. }
  2725. else if( strcasecmp(value, "CompServerShadows") == 0 ){
  2726. compMode = CompServerShadows;
  2727. for (i = 0; i < NUM_WINTYPES; ++i)
  2728. winTypeShadow[i] = True;
  2729. }
  2730. else{
  2731. compMode = CompSimple; /*default*/
  2732. for (i = 0; i < NUM_WINTYPES; ++i)
  2733. winTypeShadow[i] = False;
  2734. }
  2735. break;
  2736. case Display_:
  2737. break;
  2738. display = strdup(value);
  2739. break;
  2740. case DisableARGB:
  2741. disable_argb = ( strcasecmp(value, "true") == 0 );
  2742. break;
  2743. default:
  2744. break;
  2745. }
  2746. }
  2747. int
  2748. setParameter(char *line){
  2749. char *name = strtok(line, "=");
  2750. char *value = line+strlen(name)+1;
  2751. Option i;
  2752. for(i=Display_; i < NUMBEROFOPTIONS; i++){
  2753. if( strcasecmp(name, *(options+i) ) == 0 ){
  2754. setValue(i, value);
  2755. name = value = NULL;
  2756. return 1;
  2757. }
  2758. }
  2759. printf("ignored unknown option: <%s>\n", name);
  2760. name = value = NULL;
  2761. return 0;
  2762. }
  2763. void
  2764. loadConfig(char *filename){
  2765. FILE *file = NULL;
  2766. char line[ 1024 ];
  2767. size_t length = 0;
  2768. Bool wasNull = False;
  2769. Bool section = False;
  2770. if( filename == NULL ){
  2771. #ifdef USE_ENV_HOME
  2772. const char *home = getenv("HOME");
  2773. #else
  2774. const char *home;
  2775. struct passwd *p;
  2776. p = getpwuid(getuid());
  2777. if (p)
  2778. home = p->pw_dir;
  2779. else
  2780. home = getenv("HOME");
  2781. #endif
  2782. const char *configfile = "/.xcompmgrrc";
  2783. int n = strlen(home)+strlen(configfile)+1;
  2784. filename = (char*)malloc(n*sizeof(char));
  2785. memset(filename,0,n);
  2786. wasNull = True;
  2787. strcat(filename, home);
  2788. strcat(filename, configfile);
  2789. }
  2790. printf("trying '%s' as configfile\n\n", filename);
  2791. if( (file = fopen(filename, "r")) == NULL ){
  2792. printf("failed to open config file. does it exist?\n");
  2793. if( wasNull ){
  2794. free(filename);
  2795. filename = NULL;
  2796. }
  2797. return;
  2798. }
  2799. /*find section*/
  2800. while( !section && fgets(line, 1023, file) != NULL ){
  2801. if( strcmp(line, "[xcompmgr]\n") == 0 )
  2802. section = True;
  2803. }
  2804. /*read and set values*/
  2805. while( section && fgets(line, 1023, file) != NULL ){
  2806. int ret = strlen( line );
  2807. if( ret > 1 ){
  2808. if( *line == '[' )/*found new section - maybe check for '\n'?*/
  2809. break;
  2810. *(line+ret-1) = '\0';
  2811. setParameter(line);
  2812. }
  2813. }
  2814. printf("\nfinished parsing the config file\n");
  2815. fclose(file);
  2816. if( wasNull ){
  2817. free(filename);
  2818. filename = NULL;
  2819. }
  2820. }
  2821. void
  2822. usage (char *program)
  2823. {
  2824. fprintf (stderr, "%s v1.0\n", program);
  2825. fprintf (stderr, "usage: %s [options]\n", program);
  2826. fprintf (stderr, "Options\n");
  2827. fprintf (stderr, " -d display\n Specifies which display should be managed.\n");
  2828. fprintf (stderr, " -r radius\n Specifies the blur radius for client-side shadows. (default 12)\n");
  2829. fprintf (stderr, " -o opacity\n Specifies the translucency for client-side shadows. (default .75)\n");
  2830. fprintf (stderr, " -l left-offset\n Specifies the left offset for client-side shadows. (default -15)\n");
  2831. fprintf (stderr, " -t top-offset\n Specifies the top offset for clinet-side shadows. (default -15)\n");
  2832. fprintf (stderr, " -b color\n Specifies the background color to use if no root pixmap is set. (default is black)\n");
  2833. fprintf (stderr, " -I fade-in-step\n Specifies the opacity change between steps while fading in. (default 0.028)\n");
  2834. fprintf (stderr, " -O fade-out-step\n Specifies the opacity change between steps while fading out. (default 0.03)\n");
  2835. fprintf (stderr, " -D fade-delta-time\n Specifies the time between steps in a fade in milliseconds. (default 10)\n");
  2836. fprintf (stderr, " -a\n Use automatic server-side compositing. Faster, but no special effects.\n");
  2837. fprintf (stderr, " -c\n Draw client-side shadows with fuzzy edges.\n");
  2838. fprintf (stderr, " -C\n Avoid drawing shadows on dock/panel windows.\n");
  2839. fprintf (stderr, " -f\n Fade windows in/out when opening/closing.\n");
  2840. fprintf (stderr, " -F\n Fade windows during opacity changes.\n");
  2841. fprintf (stderr, " -n\n Normal client-side compositing with transparency support\n");
  2842. fprintf (stderr, " -s\n Draw server-side shadows with sharp edges.\n");
  2843. fprintf (stderr, " -S\n Enable synchronous operation (for debugging).\n");
  2844. fprintf (stderr, " -x [0x]XXXXXX\n Choose Custom Color in hex format\n");
  2845. fprintf (stderr, " -v\n Print version Number and exit\n");
  2846. fprintf (stderr, " -h\n Print this help\n");
  2847. my_exit_code=2;
  2848. exit (2);
  2849. }
  2850. static Bool
  2851. register_cm (void)
  2852. {
  2853. Window w;
  2854. Atom a;
  2855. static char net_wm_cm[] = "_NET_WM_CM_Sxx";
  2856. snprintf (net_wm_cm, sizeof (net_wm_cm), "_NET_WM_CM_S%d", scr);
  2857. a = XInternAtom (dpy, net_wm_cm, False);
  2858. /* w = XGetSelectionOwner (dpy, a);
  2859. if (w != None)
  2860. {
  2861. XTextProperty tp;
  2862. char **strs;
  2863. int count;
  2864. Atom winNameAtom = XInternAtom (dpy, "_NET_WM_NAME", False);
  2865. if (!XGetTextProperty (dpy, w, &tp, winNameAtom) &&
  2866. !XGetTextProperty (dpy, w, &tp, XA_WM_NAME))
  2867. {
  2868. fprintf (stderr,
  2869. "Another composite manager is already running (0x%lx)\n",
  2870. (unsigned long) w);
  2871. return False;
  2872. }
  2873. if (XmbTextPropertyToTextList (dpy, &tp, &strs, &count) == Success)
  2874. {
  2875. fprintf (stderr,
  2876. "Another composite manager is already running (%s)\n",
  2877. strs[0]);
  2878. XFreeStringList (strs);
  2879. }
  2880. XFree (tp.value);
  2881. return False;
  2882. }*/
  2883. w = XCreateSimpleWindow (dpy, RootWindow (dpy, scr), 0, 0, 1, 1, 0, None,
  2884. None);
  2885. Xutf8SetWMProperties(dpy, w, "kcompmgr", "kcompmgr", NULL, 0, NULL, NULL,
  2886. NULL);
  2887. /* setting this causes kompmgr to abort on TDE login */
  2888. /* XSetSelectionOwner (dpy, a, w, 0); */
  2889. return True;
  2890. }
  2891. int
  2892. main (int argc, char **argv)
  2893. {
  2894. XEvent ev;
  2895. Window root_return, parent_return;
  2896. Window *children;
  2897. Pixmap transPixmap;
  2898. Pixmap blackPixmap;
  2899. unsigned int nchildren;
  2900. int i;
  2901. XRenderPictureAttributes pa;
  2902. XRenderColor c;
  2903. XRectangle *expose_rects = 0;
  2904. int size_expose = 0;
  2905. int n_expose = 0;
  2906. struct pollfd ufd;
  2907. int n;
  2908. int last_update;
  2909. int now;
  2910. int p;
  2911. int composite_major, composite_minor;
  2912. Bool noDockShadow = False;
  2913. for (i = 0; i < NUM_WINTYPES; ++i) {
  2914. winTypeFade[i] = False;
  2915. winTypeShadow[i] = False;
  2916. winTypeOpacity[i] = 1.0;
  2917. }
  2918. int o;
  2919. char *fill_color_name = NULL;
  2920. char **res = NULL;
  2921. shadowColor.red = 0;
  2922. shadowColor.green = 0;
  2923. shadowColor.blue = 0;
  2924. // Initialize signal handlers
  2925. sigfillset(&block_mask);
  2926. usr_action.sa_handler = handle_siguser;
  2927. usr_action.sa_mask = block_mask;
  2928. usr_action.sa_flags = 0;
  2929. sigaction(SIGUSR1, &usr_action, NULL);
  2930. sigaction(SIGUSR2, &usr_action, NULL);
  2931. sigaction(SIGTERM, &usr_action, NULL);
  2932. loadConfig(NULL); /*we do that before cmdline-parsing, so config-values can be overridden*/
  2933. /*used for shadow colors*/
  2934. while ((o = getopt (argc, argv, "D:I:O:d:r:o:l:t:b:scnfFmCaSx:vhk")) != -1)
  2935. {
  2936. switch (o) {
  2937. case 'd':
  2938. display = optarg;
  2939. break;
  2940. case 'D':
  2941. fade_delta = atoi (optarg);
  2942. if (fade_delta < 1)
  2943. fade_delta = 10;
  2944. break;
  2945. case 'I':
  2946. fade_in_step = atof (optarg);
  2947. if (fade_in_step <= 0)
  2948. fade_in_step = 0.01;
  2949. break;
  2950. case 'O':
  2951. fade_out_step = atof (optarg);
  2952. if (fade_out_step <= 0)
  2953. fade_out_step = 0.01;
  2954. break;
  2955. case 's':
  2956. compMode = CompServerShadows;
  2957. for (i = 0; i < NUM_WINTYPES; ++i)
  2958. winTypeShadow[i] = True;
  2959. break;
  2960. case 'c':
  2961. compMode = CompClientShadows;
  2962. for (i = 0; i < NUM_WINTYPES; ++i)
  2963. winTypeShadow[i] = True;
  2964. break;
  2965. case 'C':
  2966. winTypeShadow[WINTYPE_DOCK] = False;
  2967. break;
  2968. case 'n':
  2969. compMode = CompSimple;
  2970. for (i = 0; i < NUM_WINTYPES; ++i)
  2971. winTypeShadow[i] = False;
  2972. break;
  2973. case 'f':
  2974. for (i = 0; i < NUM_WINTYPES; ++i) {
  2975. if (i != WINTYPE_POPUP_MENU)
  2976. winTypeFade[i] = True;
  2977. }
  2978. break;
  2979. case 'm':
  2980. winTypeFade[WINTYPE_POPUP_MENU] = True;
  2981. break;
  2982. case 'F':
  2983. fadeTrans = True;
  2984. break;
  2985. case 'a':
  2986. autoRedirect = True;
  2987. break;
  2988. case 'S':
  2989. synchronize = True;
  2990. break;
  2991. case 'r':
  2992. shadowRadius = atoi (optarg);
  2993. break;
  2994. case 'o':
  2995. shadowOpacity = atof (optarg);
  2996. break;
  2997. case 'l':
  2998. shadowOffsetX = atoi (optarg);
  2999. break;
  3000. case 't':
  3001. shadowOffsetY = atoi (optarg);
  3002. break;
  3003. case 'b':
  3004. fill_color_name = optarg;
  3005. break;
  3006. case 'x':
  3007. if( compMode != CompClientShadows ){
  3008. fprintf(stderr, "sorry, but we need ClientShadows (-c) for coloring to work properly!\ndefaulting to black...\n");
  3009. break;
  3010. }
  3011. setShadowColor(optarg);
  3012. break;
  3013. case 'v': fprintf (stderr, "%s v%-3.2f\n", argv[0], _VERSION_); my_exit_code=0; exit (0);
  3014. case 'k':
  3015. restartOnSigterm = False;
  3016. break;
  3017. case 'h':
  3018. default:
  3019. usage (argv[0]);
  3020. break;
  3021. }
  3022. }
  3023. /* don't bother to do anything for the desktop */
  3024. winTypeOpacity[WINTYPE_DESKTOP] = 1.0;
  3025. winTypeShadow[WINTYPE_DESKTOP] = False;
  3026. winTypeFade[WINTYPE_DESKTOP] = False;
  3027. dpy = XOpenDisplay (display);
  3028. if (!dpy)
  3029. {
  3030. fprintf (stderr, "Can't open display\n");
  3031. my_exit_code=2;
  3032. exit (2);
  3033. }
  3034. XSetErrorHandler (error);
  3035. if (synchronize)
  3036. XSynchronize (dpy, 1);
  3037. scr = DefaultScreen (dpy);
  3038. root = RootWindow (dpy, scr);
  3039. if (!XRenderQueryExtension (dpy, &render_event, &render_error))
  3040. {
  3041. fprintf (stderr, "No render extension\n");
  3042. my_exit_code=2;
  3043. exit (2);
  3044. }
  3045. if (!XQueryExtension (dpy, COMPOSITE_NAME, &composite_opcode,
  3046. &composite_event, &composite_error))
  3047. {
  3048. fprintf (stderr, "No composite extension\n");
  3049. my_exit_code=2;
  3050. exit (2);
  3051. }
  3052. XCompositeQueryVersion (dpy, &composite_major, &composite_minor);
  3053. #if HAS_NAME_WINDOW_PIXMAP
  3054. if (composite_major > 0 || composite_minor >= 2)
  3055. hasNamePixmap = True;
  3056. #endif
  3057. if (!XDamageQueryExtension (dpy, &damage_event, &damage_error))
  3058. {
  3059. fprintf (stderr, "No damage extension\n");
  3060. my_exit_code=2;
  3061. exit (2);
  3062. }
  3063. if (!XFixesQueryExtension (dpy, &xfixes_event, &xfixes_error))
  3064. {
  3065. fprintf (stderr, "No XFixes extension\n");
  3066. my_exit_code=2;
  3067. exit (2);
  3068. }
  3069. if (!XShapeQueryExtension (dpy, &xshape_event, &xshape_error))
  3070. {
  3071. fprintf (stderr, "No XShape extension\n");
  3072. my_exit_code=2;
  3073. exit (2);
  3074. }
  3075. fprintf(stderr, "Started\n");
  3076. if (!register_cm())
  3077. {
  3078. my_exit_code=2;
  3079. exit (2);
  3080. }
  3081. /* get atoms */
  3082. shadowAtom = XInternAtom (dpy, SHADOW_PROP, False);
  3083. opacityAtom = XInternAtom (dpy, OPACITY_PROP, False);
  3084. shadeAtom = XInternAtom (dpy, SHADE_PROP, False);
  3085. shapableAtom = XInternAtom (dpy, SHAPABLE_PROP, False);
  3086. decoHashAtom = XInternAtom (dpy, DECOHASH_PROP, False);
  3087. dimAtom = XInternAtom (dpy, DIM_PROP, False);
  3088. deskChangeAtom = XInternAtom (dpy, DESKCHANGE_PROP, False);
  3089. winTypeAtom = XInternAtom (dpy, "_NET_WM_WINDOW_TYPE", False);
  3090. winTDETTDAtom = XInternAtom (dpy, "_KDE_TRANSPARENT_TO_DESKTOP", False);
  3091. winType[WINTYPE_DESKTOP] = XInternAtom (dpy, "_NET_WM_WINDOW_TYPE_DESKTOP", False);
  3092. winType[WINTYPE_DOCK] = XInternAtom (dpy, "_NET_WM_WINDOW_TYPE_DOCK", False);
  3093. winType[WINTYPE_TOOLBAR] = XInternAtom (dpy, "_NET_WM_WINDOW_TYPE_TOOLBAR", False);
  3094. winType[WINTYPE_MENU] = XInternAtom (dpy, "_NET_WM_WINDOW_TYPE_MENU", False);
  3095. winType[WINTYPE_UTILITY] = XInternAtom (dpy, "_NET_WM_WINDOW_TYPE_UTILITY", False);
  3096. winType[WINTYPE_SPLASH] = XInternAtom (dpy, "_NET_WM_WINDOW_TYPE_SPLASH", False);
  3097. winType[WINTYPE_DIALOG] = XInternAtom (dpy, "_NET_WM_WINDOW_TYPE_DIALOG", False);
  3098. winType[WINTYPE_NORMAL] = XInternAtom (dpy, "_NET_WM_WINDOW_TYPE_NORMAL", False);
  3099. winType[WINTYPE_DROPDOWN_MENU] = XInternAtom (dpy, "_NET_WM_WINDOW_TYPE_DROPDOWN_MENU", False);
  3100. winType[WINTYPE_POPUP_MENU] = XInternAtom (dpy, "_NET_WM_WINDOW_TYPE_POPUP_MENU", False);
  3101. winType[WINTYPE_TOOLTIP] = XInternAtom (dpy, "_NET_WM_WINDOW_TYPE_TOOLTIP", False);
  3102. winType[WINTYPE_NOTIFY] = XInternAtom (dpy, "_NET_WM_WINDOW_TYPE_NOTIFICATION", False);
  3103. winType[WINTYPE_COMBO] = XInternAtom (dpy, "_NET_WM_WINDOW_TYPE_COMBO", False);
  3104. winType[WINTYPE_DND] = XInternAtom (dpy, "_NET_WM_WINDOW_TYPE_DND", False);
  3105. pa.subwindow_mode = IncludeInferiors;
  3106. if (compMode == CompClientShadows)
  3107. {
  3108. gaussianMap = make_gaussian_map(dpy, shadowRadius);
  3109. presum_gaussian (gaussianMap);
  3110. }
  3111. if (fill_color_name)
  3112. {
  3113. XColor c;
  3114. if (! XParseColor (dpy, DefaultColormap (dpy, scr),
  3115. fill_color_name, &c))
  3116. {
  3117. fprintf (stderr, "Could not parse fill color.\n");
  3118. my_exit_code=2;
  3119. exit (2);
  3120. }
  3121. if (! XAllocColor (dpy, DefaultColormap (dpy, scr), &c))
  3122. {
  3123. fprintf (stderr, "Could not allocate color.\n");
  3124. my_exit_code=2;
  3125. exit (2);
  3126. }
  3127. fill_color.red = c.red;
  3128. fill_color.green = c.green;
  3129. fill_color.blue = c.blue;
  3130. }
  3131. else
  3132. {
  3133. fill_color.red = fill_color.green = fill_color.blue = 0x0;
  3134. }
  3135. fill_color.alpha = 0xffff;
  3136. root_width = DisplayWidth (dpy, scr);
  3137. root_height = DisplayHeight (dpy, scr);
  3138. rootPicture = XRenderCreatePicture (dpy, root,
  3139. sXRenderFindVisualFormat (dpy,
  3140. DefaultVisual (dpy, scr)),
  3141. CPSubwindowMode,
  3142. &pa);
  3143. blackPicture = solid_picture (dpy, True, 1, (double)(shadowColor.red)/0xff, (double)(shadowColor.green)/0xff, (double)(shadowColor.blue)/0xff);
  3144. if (compMode == CompServerShadows)
  3145. transBlackPicture = solid_picture (dpy, True, 0.3, 0, 0, 0);
  3146. allDamage = None;
  3147. clipChanged = True;
  3148. XGrabServer (dpy);
  3149. if (autoRedirect)
  3150. XCompositeRedirectSubwindows (dpy, root, CompositeRedirectAutomatic);
  3151. else
  3152. {
  3153. int dummy;
  3154. XCompositeRedirectSubwindows (dpy, root, CompositeRedirectManual);
  3155. XSelectInput (dpy, root,
  3156. SubstructureNotifyMask|
  3157. ExposureMask|
  3158. StructureNotifyMask|
  3159. PropertyChangeMask |
  3160. VisibilityChangeMask);
  3161. /*shaping stuff*/
  3162. XShapeQueryExtension(dpy, &shapeEvent, &dummy);
  3163. XShapeSelectInput (dpy, root, ShapeNotifyMask);
  3164. XQueryTree (dpy, root, &root_return, &parent_return, &children, &nchildren);
  3165. for (i = 0; i < nchildren; i++)
  3166. add_win (dpy, children[i], i ? children[i-1] : None);
  3167. XFree (children);
  3168. }
  3169. XUngrabServer (dpy);
  3170. ufd.fd = ConnectionNumber (dpy);
  3171. ufd.events = POLLIN;
  3172. if (!autoRedirect)
  3173. paint_all (dpy, None);
  3174. /* Under no circumstances should these two lines EVER be moved earlier in main() than this point */
  3175. atexit(delete_pid_file);
  3176. write_pid_file(getpid());
  3177. for (;;)
  3178. {
  3179. /* dump_wins (); */
  3180. do {
  3181. if (autoRedirect)
  3182. XFlush (dpy);
  3183. if (!QLength (dpy))
  3184. {
  3185. if (poll (&ufd, 1, fade_timeout()) == 0)
  3186. {
  3187. run_fades (dpy);
  3188. break;
  3189. }
  3190. }
  3191. XNextEvent (dpy, &ev);
  3192. if ((ev.type & 0x7f) != KeymapNotify)
  3193. discard_ignore (dpy, ev.xany.serial);
  3194. #if DEBUG_EVENTS
  3195. printf ("event %10.10s serial 0x%08x window 0x%08x\n",
  3196. ev_name(&ev), ev_serial (&ev), ev_window (&ev));
  3197. #endif
  3198. if (!autoRedirect) switch (ev.type) {
  3199. case CreateNotify:
  3200. add_win (dpy, ev.xcreatewindow.window, 0);
  3201. break;
  3202. case ConfigureNotify:
  3203. configure_win (dpy, &ev.xconfigure);
  3204. break;
  3205. case DestroyNotify:
  3206. destroy_win (dpy, ev.xdestroywindow.window, True, True);
  3207. break;
  3208. case MapNotify:
  3209. map_win (dpy, ev.xmap.window, ev.xmap.serial, True);
  3210. break;
  3211. case UnmapNotify:
  3212. unmap_win (dpy, ev.xunmap.window, True);
  3213. break;
  3214. case ReparentNotify:
  3215. if (ev.xreparent.parent == root)
  3216. add_win (dpy, ev.xreparent.window, 0);
  3217. else
  3218. destroy_win (dpy, ev.xreparent.window, False, True);
  3219. break;
  3220. case CirculateNotify:
  3221. circulate_win (dpy, &ev.xcirculate);
  3222. break;
  3223. case Expose:
  3224. if (ev.xexpose.window == root)
  3225. {
  3226. int more = ev.xexpose.count + 1;
  3227. if (n_expose == size_expose)
  3228. {
  3229. if (expose_rects)
  3230. {
  3231. expose_rects = realloc (expose_rects,
  3232. (size_expose + more) *
  3233. sizeof (XRectangle));
  3234. size_expose += more;
  3235. }
  3236. else
  3237. {
  3238. expose_rects = malloc (more * sizeof (XRectangle));
  3239. size_expose = more;
  3240. }
  3241. }
  3242. expose_rects[n_expose].x = ev.xexpose.x;
  3243. expose_rects[n_expose].y = ev.xexpose.y;
  3244. expose_rects[n_expose].width = ev.xexpose.width;
  3245. expose_rects[n_expose].height = ev.xexpose.height;
  3246. n_expose++;
  3247. if (ev.xexpose.count == 0)
  3248. {
  3249. expose_root (dpy, root, expose_rects, n_expose);
  3250. n_expose = 0;
  3251. }
  3252. }
  3253. break;
  3254. case PropertyNotify:
  3255. for (p = 0; backgroundProps[p]; p++)
  3256. {
  3257. if (ev.xproperty.atom == XInternAtom (dpy, backgroundProps[p], False))
  3258. {
  3259. if (rootTile)
  3260. {
  3261. XRenderFreePicture (dpy, rootTile);
  3262. rootTile = None;
  3263. damage_screen (dpy);
  3264. break;
  3265. }
  3266. }
  3267. }
  3268. /* Window set shade? */
  3269. if (ev.xproperty.atom == shadeAtom)
  3270. {
  3271. win * w = find_win(dpy, ev.xproperty.window);
  3272. if (w){
  3273. unsigned int tmp = get_shade_prop(dpy, w);
  3274. if (tmp)
  3275. {
  3276. if (tmp == 1)
  3277. {
  3278. w->preShadeOpacity = w->opacity;
  3279. w->opacity = w->opacity-1; /*assuming that no human being will ever be able to shade an invisable window ;) */
  3280. determine_mode(dpy, w);
  3281. }
  3282. else if (tmp == 2)
  3283. {
  3284. w->opacity = w->preShadeOpacity;
  3285. determine_mode(dpy, w);
  3286. }
  3287. }
  3288. break;
  3289. }
  3290. }
  3291. else if (ev.xproperty.atom == shapableAtom)
  3292. {
  3293. win * w = find_win(dpy, ev.xproperty.window);
  3294. if (w)
  3295. {
  3296. w->shapable = get_shapable_prop(dpy, w);
  3297. /* printf("%u is %s shapable\n",w->id,w->shapable?"":"not");*/
  3298. }
  3299. else
  3300. printf("arrrg, window not found\n");
  3301. }
  3302. else if (ev.xproperty.atom == decoHashAtom)
  3303. {
  3304. win * w = find_win(dpy, ev.xproperty.window);
  3305. if (w)
  3306. {
  3307. w->decoHash = get_decoHash_prop(dpy, w);
  3308. }
  3309. else
  3310. printf("arrrg, window not found\n");
  3311. }
  3312. else if (ev.xproperty.atom == dimAtom)
  3313. {
  3314. win * w = find_win(dpy, ev.xproperty.window);
  3315. if (w)
  3316. {
  3317. unsigned int tmp = get_dim_prop(dpy, w);
  3318. if (w->dimPicture)
  3319. {
  3320. XRenderFreePicture (dpy, w->dimPicture);
  3321. w->dimPicture = None;
  3322. }
  3323. if (tmp < OPAQUE)
  3324. w->dimPicture = solid_picture (dpy, True, (double)tmp/OPAQUE, 0.1, 0.1, 0.1);
  3325. }
  3326. else
  3327. printf("arrrg, window not found\n");
  3328. }
  3329. /* check if Trans or Shadow property was changed */
  3330. else if (ev.xproperty.atom == opacityAtom || ev.xproperty.atom == shadowAtom)
  3331. {
  3332. /* reset mode and redraw window */
  3333. win * w = find_win(dpy, ev.xproperty.window);
  3334. if (w)
  3335. {
  3336. unsigned int tmp;
  3337. unsigned int oldShadowSize = w->shadowSize;
  3338. if (ev.xproperty.atom == opacityAtom)
  3339. {
  3340. tmp = get_opacity_prop(dpy, w, OPAQUE);
  3341. /*This will most probably happen if window is in fade - resulting in that the fade process isn't updated or broken -> we may have a wrong opacity in the future*/
  3342. /*if (tmp == w->opacity)
  3343. break;*/ /*skip if opacity does not change*/
  3344. if (fadeTrans)
  3345. {
  3346. static double start, finish, step;
  3347. start = w->opacity*1.0/OPAQUE;
  3348. finish = (tmp*1.0)/OPAQUE;
  3349. if ( start > finish )
  3350. step = fade_out_step;
  3351. else
  3352. step = fade_in_step;
  3353. set_fade (dpy, w, start, finish, step, 0, False, True, True, False);
  3354. break;
  3355. }
  3356. else {
  3357. w->opacity = tmp;
  3358. }
  3359. }
  3360. else
  3361. {
  3362. tmp = get_shadow_prop(dpy, w);
  3363. if (tmp == w->shadowSize)
  3364. break; /*skip if shadow does not change*/
  3365. w->shadowSize = tmp;
  3366. /* if (w->isInFade)
  3367. break; */
  3368. }
  3369. if (w->shadow)
  3370. {
  3371. XRenderFreePicture (dpy, w->shadow);
  3372. w->shadow = None;
  3373. }
  3374. if (oldShadowSize < w->shadowSize) /* this is important to catch size changes on cleanup with determine_mode*/
  3375. {
  3376. if( w->extents != None )
  3377. XFixesDestroyRegion( dpy, w->extents );
  3378. w->extents = win_extents (dpy, w);
  3379. determine_mode(dpy, w);
  3380. }
  3381. else
  3382. {
  3383. determine_mode(dpy, w);
  3384. if( w->extents != None )
  3385. XFixesDestroyRegion( dpy, w->extents );
  3386. w->extents = win_extents (dpy, w);
  3387. }
  3388. }
  3389. }
  3390. else if (ev.xproperty.atom == deskChangeAtom)
  3391. {
  3392. /*just set global variable*/
  3393. unsigned int tmp = get_deskchange_prop(dpy, ev.xproperty.window);
  3394. printf("desk change, state:%d\n",tmp);
  3395. }
  3396. break;
  3397. default:
  3398. if (ev.type == damage_event + XDamageNotify)
  3399. {
  3400. /* printf("damaging win: %u\n",ev.xany.window);*/
  3401. damage_win (dpy, (XDamageNotifyEvent *) &ev);
  3402. repaint_root_overlay_window();
  3403. }
  3404. if (ev.type == xshape_event + ShapeNotify)
  3405. {
  3406. shape_win (dpy, (XShapeEvent *) &ev);
  3407. }
  3408. if (ev.type == shapeEvent)
  3409. {
  3410. win * w = find_win(dpy, ev.xany.window);
  3411. #if 1
  3412. if (w && w->shapable)
  3413. #endif
  3414. #if 0
  3415. if (w)
  3416. #endif
  3417. {
  3418. #if 0
  3419. XRectangle rect;
  3420. rect.x = ((XShapeEvent*)&ev)->x;
  3421. rect.y = ((XShapeEvent*)&ev)->y;
  3422. rect.width = ((XShapeEvent*)&ev)->width;
  3423. rect.height = ((XShapeEvent*)&ev)->height;
  3424. damage_shape(dpy, w, &rect);
  3425. #endif
  3426. #if 0
  3427. if (w->shadowSize != 0)
  3428. {
  3429. w->shadowSize = 0;
  3430. XRenderFreePicture (dpy, w->shadow);
  3431. w->shadow = None;
  3432. determine_mode(dpy, w);
  3433. if( w->extents != None )
  3434. XFixesDestroyRegion( dpy, w->extents );
  3435. w->extents = win_extents (dpy, w);
  3436. }
  3437. #endif
  3438. /*this is hardly efficient, but a current workaraound
  3439. shaping support isn't that good so far (e.g. we lack shaped shadows)
  3440. IDEA: use XRender to scale/shift a copy of the window and then blur it*/
  3441. #if 1
  3442. if (w->picture)
  3443. {
  3444. clipChanged = True;
  3445. repair_win (dpy, w);
  3446. }
  3447. #endif
  3448. }
  3449. }
  3450. break;
  3451. }
  3452. } while (QLength (dpy));
  3453. if (allDamage && !autoRedirect)
  3454. {
  3455. paint_all (dpy, allDamage);
  3456. XSync (dpy, False);
  3457. allDamage = None;
  3458. clipChanged = False;
  3459. }
  3460. }
  3461. XClearArea (dpy, root, 0, 0, 0, 0, True);
  3462. XSync (dpy, False);
  3463. }