From 991c7956290fe4aed82737d1fc67ef2f42caf462 Mon Sep 17 00:00:00 2001 From: Thomas Brunko Date: Sun, 12 Apr 2009 13:54:29 +0200 Subject: [PATCH] awful.titlebar: more buttons added This is a new version of 'titlebar.lua'. There are now additional buttons for: - setting the 'ontop' attribute - setting the 'sticky' attribute - maximizing the client In addition to changing the state of the client the buttons also show if the corresponding state is active for a client. All new buttons now require 4 images for: - unfocused window, state inactive (i.e. ontop == false) - unfocused window, state active (i.e. ontop == true) - focused window, state inactive (i.e. ontop == false) - focused window, state active (i.e. ontop == true) It's not difficult to add more buttons with any kind of functionality. User configuration is currently restricted to theming of the buttons. Buttons are disabled simply by not configuring them in the theme. The icons for the new buttons are taken from kde4. They're not really pretty but they're OK to demonstrate the new features. Signed-off-by: Julien Danjou --- lib/awful/titlebar.lua.in | 274 +++++++++++++++--- themes/default/theme.in | 24 +- themes/default/titlebar/close.png | Bin 358 -> 358 bytes themes/default/titlebar/close_focus.png | Bin 0 -> 666 bytes themes/default/titlebar/close_normal.png | Bin 0 -> 431 bytes .../titlebar/floating_focus_active.png | Bin 0 -> 598 bytes .../titlebar/floating_focus_inactive.png | Bin 0 -> 414 bytes .../titlebar/floating_normal_active.png | Bin 0 -> 386 bytes .../titlebar/floating_normal_inactive.png | Bin 0 -> 349 bytes .../titlebar/maximized_focus_active.png | Bin 0 -> 1013 bytes .../titlebar/maximized_focus_inactive.png | Bin 0 -> 816 bytes .../titlebar/maximized_normal_active.png | Bin 0 -> 738 bytes .../titlebar/maximized_normal_inactive.png | Bin 0 -> 682 bytes .../default/titlebar/ontop_focus_active.png | Bin 0 -> 774 bytes .../default/titlebar/ontop_focus_inactive.png | Bin 0 -> 669 bytes .../default/titlebar/ontop_normal_active.png | Bin 0 -> 565 bytes .../titlebar/ontop_normal_inactive.png | Bin 0 -> 590 bytes .../default/titlebar/sticky_focus_active.png | Bin 0 -> 833 bytes .../titlebar/sticky_focus_inactive.png | Bin 0 -> 659 bytes .../default/titlebar/sticky_normal_active.png | Bin 0 -> 611 bytes .../titlebar/sticky_normal_inactive.png | Bin 0 -> 597 bytes 21 files changed, 249 insertions(+), 49 deletions(-) create mode 100644 themes/default/titlebar/close_focus.png create mode 100644 themes/default/titlebar/close_normal.png create mode 100644 themes/default/titlebar/floating_focus_active.png create mode 100644 themes/default/titlebar/floating_focus_inactive.png create mode 100644 themes/default/titlebar/floating_normal_active.png create mode 100644 themes/default/titlebar/floating_normal_inactive.png create mode 100644 themes/default/titlebar/maximized_focus_active.png create mode 100644 themes/default/titlebar/maximized_focus_inactive.png create mode 100644 themes/default/titlebar/maximized_normal_active.png create mode 100644 themes/default/titlebar/maximized_normal_inactive.png create mode 100644 themes/default/titlebar/ontop_focus_active.png create mode 100644 themes/default/titlebar/ontop_focus_inactive.png create mode 100644 themes/default/titlebar/ontop_normal_active.png create mode 100644 themes/default/titlebar/ontop_normal_inactive.png create mode 100644 themes/default/titlebar/sticky_focus_active.png create mode 100644 themes/default/titlebar/sticky_focus_inactive.png create mode 100644 themes/default/titlebar/sticky_normal_active.png create mode 100644 themes/default/titlebar/sticky_normal_inactive.png diff --git a/lib/awful/titlebar.lua.in b/lib/awful/titlebar.lua.in index 04b27366..4296cf76 100644 --- a/lib/awful/titlebar.lua.in +++ b/lib/awful/titlebar.lua.in @@ -28,6 +28,9 @@ module("awful.titlebar") -- Privata data local data = otable() +-- Predeclaration for buttons +local button_groups + --- Create a standard titlebar. -- @param c The client. -- @param args Arguments. @@ -71,52 +74,28 @@ function add(c, args) local appicon = capi.widget({ type = "imagebox", align = "left" }) appicon.image = c.icon - -- Also redirect events for appicon (So the entire titlebar behaves consistently) - appicon:buttons(bts) - function appicon.mouse_enter(s) hooks.user.call('mouse_enter', c) end - - local closef - if theme.titlebar_close_button_focus then - closef = widget.button({ align = "right", - image = image(theme.titlebar_close_button_focus) }) - end - - local close - if theme.titlebar_close_button_normal then - close = widget.button({ align = "right", - image = image(theme.titlebar_close_button_normal) }) - end - - if close or closef then - -- Bind kill button, also allow moving and resizing on this widget - local bts = - { - capi.button({ }, 1, nil, function (t) t.client:kill() end), - capi.button({ args.modkey }, 1, function (t) mouse.client.move(t.client) end), - capi.button({ args.modkey }, 3, function (t) mouse.client.resize(t.client) end) - } - if close then - local rbts = close:buttons() - for k, v in pairs(rbts) do - bts[#bts + 1] = v + -- for each button group, call create for the client. + -- if a button set is created add the set to the + -- data[c].button_sets for late updates and add the + -- individual buttons to the array part of the widget + -- list + local widget_list = { appicon = appicon, title = title } + local iw = #widget_list + local is = 1 + data[c].button_sets = {} + for i = 1, #button_groups do + local set = button_groups[i].create(c, modkey, theme) + if (set) then + data[c].button_sets[is] = set + is = is + 1 + for n,b in pairs(set) do + widget_list[iw] = b + iw = iw + 1 end - close:buttons(bts) - function close.mouse_enter(s) hooks.user.call('mouse_enter', c) end - end - if closef then - local rbts = closef:buttons() - for k, v in pairs(rbts) do - bts[#bts + 1] = v - end - closef:buttons(bts) - -- Needed for sloppy focus beheaviour - function closef.mouse_enter(s) hooks.user.call('mouse_enter', c) end end end - tb.widgets = { appicon = appicon, title = title, - closef = closef, close = close } - + tb.widgets = widget_list c.titlebar = tb update(c) @@ -126,7 +105,7 @@ end -- @param c The client to update. -- @param prop The property name which has changed. function update(c, prop) - if c.titlebar and data[c] then + if c.titlebar and data[c] then local widgets = c.titlebar.widgets if prop == "name" then if widgets.title then @@ -140,13 +119,15 @@ function update(c, prop) if capi.client.focus == c then c.titlebar.fg = data[c].fg_focus c.titlebar.bg = data[c].bg_focus - if widgets.closef then widgets.closef.visible = true end - if widgets.close then widgets.close.visible = false end else c.titlebar.fg = data[c].fg c.titlebar.bg = data[c].bg - if widgets.closef then widgets.closef.visible = false end - if widgets.close then widgets.close.visible = true end + end + + -- iterated of all registered button_sets and update + local sets = data[c].button_sets + for i = 1, #sets do + sets[i].update(c,prop) end end end @@ -158,6 +139,205 @@ function remove(c) data[c] = nil end +-- Create a new button for the toolbar +-- @param c The client of the titlebar +-- @param name The base name of the button (i.e. close) +-- @param modkey ... you know that one, don't you? +-- @param theme The theme from beautifull. Used to get the image paths +-- @param state The state the button is associated to. Containse path the action and info about the image +local function button_new(c, name, modkey, theme, state) + local bts = + { + capi.button({ }, 1, nil, state.action), + capi.button({ modkey }, 1, function (t) mouse.client.move(t.client) end), + capi.button({ modkey }, 3, function (t) mouse.client.resize(t.client) end) + } + + -- get the image path from the theme. Only return a button if we find an image + local img + img = "titlebar_" .. name .. "_button_" .. state.img + img = theme[img] + if not img then return end + img = image(img) + if not img then return end + + -- now create the button + local bname = name .. "_" .. state.idx + local button = widget.button({ image = img }) + if not button then return end + local rbts = button:buttons() + + for k, v in pairs(rbts) do + bts[#bts + 1] = v + end + + button:buttons(bts) + function button.mouse_enter(s) hooks.user.call('mouse_enter', c) end + button.visible = false + return button +end + +-- Update the buttons in a button group +-- @param s The button group to update +-- @param c The client of the titlebar +-- @param p The property that has changed +local function button_group_update(s,c,p) + -- hide the currently active button, get the new state and show the new button + local n = s.select_state(c,p) + if n == nil then return end + if (s.active ~= nil) then s.active.visible = false end + s.active = s.buttons[n] + s.active.visible = true +end + +-- Create all buttons in a group +-- @param c The client of the titlebar +-- @param group The button group to create the buttons for +-- @param modkey ... +-- @param theme Theme for the image paths +local function button_group_create(c, group, modkey, theme ) + local s = {} + s.name = group.name + s.select_state = group.select_state + s.buttons = {} + for n,state in pairs(group.states) do + s.buttons[n] = button_new(c, s.name, modkey, theme, state) + if (s.buttons[n] == nil) then return end + for a,v in pairs(group.attributes) do + s.buttons[n][a] = v + end + end + function s.update(c,p) button_group_update(s,c,p) end + return s +end + +-- Builds a new button group +-- @param name The base name for the buttons in the group (i.e. "close") +-- @param attrs Common attributes for the buttons (i.e. {align = "right") +-- @param sfn State select function. +-- @param args The states of the button +local function button_group(name, attrs, sfn, ...) + local s = {} + s.name = name + s.select_state = sfn + s.attributes = attrs + s.states = {} + + for i = 1, #arg do + local state = arg[i] + s.states[state.idx] = state + end + + function s.create(c,modkey, theme) return button_group_create(c,s,modkey, theme) end + return s +end + +-- Select a state for a client based on an attribute of the client and whether it has focus +-- @param c The client of the titlebar +-- @param p The property that has changed +-- @param a The property to check +local function select_state(c,p,a) + if (c == nil) then return "n/i" end + if capi.client.focus == c then + if c[a] then + return "f/a" + else + return "f/i" + end + else + if c[a] then + return "n/a" + else + return "n/i" + end + end +end + +-- Select a state for a client based on whether it's maximized or not +-- @param c The client of the titlebar +-- @param p The property that has changed +local function select_state_maximized(c,p) + if (c == nil) then return "n/i" end + if capi.client.focus == c then + if c.maximized_horizontal or c.maximized_vertical then + return "f/a" + else + return "f/i" + end + else + if c.maximized_horizontal or c.maximized_vertical then + return "n/a" + else + return "n/i" + end + end +end + +-- Select a state for a client based on whether it has focus or not +-- @param c The client of the titlebar +-- @param p The property that has changed +local function select_state_focus(c,p) + if c and capi.client.focus == c then + return "f" + end + return "n" +end + +-- These are the predefined button groups +-- A short explanation using 'close_buttons' as an example: +-- "close" : name of the button, the images for this button are taken from the +-- theme variables titlebar_close_button_... +-- { align ... : attributes of all the buttons +-- select_state_focus : This function returns a short string used to describe +-- the state. In this case either "n" or "f" depending on +-- the focus state of the client. These strings can be +-- choosen freely but the< must match one of the idx fuekds +-- of the states below +-- { idx = "n" ... : This is the state of the button for the 'unfocussed' +-- (normal) state. The idx = "n" parameter connects this +-- button to the return value of the 'select_state_focus' +-- function. The img = "normal" parameter is used to +-- determine its image. In this case the iamge is taken from +-- the theme variable "titlebar_close_button_normal". +-- Finally the last parameter is the action for mouse +-- button 1 + +local close_buttons = button_group("close", + { align = "left"}, + select_state_focus, + { idx = "n", img = "normal", action = function (t) t.client:kill() end}, + { idx = "f", img = "focus", action = function (t) t.client:kill() end} + ) + +local ontop_buttons = button_group("ontop", + { align = "right"}, + function(c,p) return select_state(c, p, "ontop") end, + { idx = "n/i", img = "normal_inactive", action = function(t) t.client.ontop = true ; update(t.client) end}, + { idx = "f/i", img = "focus_inactive", action = function(t) t.client.ontop = true ; update(t.client) end}, + { idx = "n/a", img = "normal_active", action = function(t) t.client.ontop = false ; update(t.client) end}, + { idx = "f/a", img = "focus_active", action = function(t) t.client.ontop = false ; update(t.client) end} + ) + +local sticky_buttons = button_group("sticky", + { align = "right"}, + function(c,p) return select_state(c,p,"sticky") end, + { idx = "n/i", img = "normal_inactive", action = function(t) t.client.sticky = true ; update(t.client) end}, + { idx = "f/i", img = "focus_inactive", action = function(t) t.client.sticky = true ; update(t.client) end}, + { idx = "n/a", img = "normal_active", action = function(t) t.client.sticky = false ; update(t.client) end}, + { idx = "f/a", img = "focus_active", action = function(t) t.client.sticky = false ; update(t.client) end} + ) + +local maximized_buttons = button_group("maximized", + { align = "right"}, + select_state_maximized, + { idx = "n/i", img = "normal_inactive", action = function(t) t.client.maximized_horizontal = true ; t.client.maximized_vertical = true ; update(t.client) end}, + { idx = "f/i", img = "focus_inactive", action = function(t) t.client.maximized_horizontal = true ; t.client.maximized_vertical = true ; update(t.client) end}, + { idx = "n/a", img = "normal_active", action = function(t) t.client.maximized_horizontal = false ; t.client.maximized_vertical = false ; update(t.client) end}, + { idx = "f/a", img = "focus_active", action = function(t) t.client.maximized_horizontal = false ; t.client.maximized_vertical = false ; update(t.client) end} + ) + +button_groups = { ontop_buttons, sticky_buttons, maximized_buttons, close_buttons} + -- Register standards hooks hooks.focus.register(update) hooks.unfocus.register(update) diff --git a/themes/default/theme.in b/themes/default/theme.in index 3c68c410..c5fbdf6d 100644 --- a/themes/default/theme.in +++ b/themes/default/theme.in @@ -46,8 +46,28 @@ menu_width = 100 #bg_widget = #cc0000 # Define the image to load -titlebar_close_button_normal = @AWESOME_THEMES_PATH@/default/titlebar/close.png -titlebar_close_button_focus = @AWESOME_THEMES_PATH@/default/titlebar/closer.png +titlebar_close_button_normal = @AWESOME_THEMES_PATH@/default/titlebar/close_normal.png +titlebar_close_button_focus = @AWESOME_THEMES_PATH@/default/titlebar/close_focus.png + +titlebar_ontop_button_normal_inactive = @AWESOME_THEMES_PATH@/default/titlebar/ontop_normal_inactive.png +titlebar_ontop_button_focus_inactive = @AWESOME_THEMES_PATH@/default/titlebar/ontop_focus_inactive.png +titlebar_ontop_button_normal_active = @AWESOME_THEMES_PATH@/default/titlebar/ontop_normal_active.png +titlebar_ontop_button_focus_active = @AWESOME_THEMES_PATH@/default/titlebar/ontop_focus_active.png + +titlebar_sticky_button_normal_inactive = @AWESOME_THEMES_PATH@/default/titlebar/sticky_normal_inactive.png +titlebar_sticky_button_focus_inactive = @AWESOME_THEMES_PATH@/default/titlebar/sticky_focus_inactive.png +titlebar_sticky_button_normal_active = @AWESOME_THEMES_PATH@/default/titlebar/sticky_normal_active.png +titlebar_sticky_button_focus_active = @AWESOME_THEMES_PATH@/default/titlebar/sticky_focus_active.png + +titlebar_floating_button_normal_inactive = @AWESOME_THEMES_PATH@/default/titlebar/floating_normal_inactive.png +titlebar_floating_button_focus_inactive = @AWESOME_THEMES_PATH@/default/titlebar/floating_focus_inactive.png +titlebar_floating_button_normal_active = @AWESOME_THEMES_PATH@/default/titlebar/floating_normal_active.png +titlebar_floating_button_focus_active = @AWESOME_THEMES_PATH@/default/titlebar/floating_focus_active.png + +titlebar_maximized_button_normal_inactive = @AWESOME_THEMES_PATH@/default/titlebar/maximized_normal_inactive.png +titlebar_maximized_button_focus_inactive = @AWESOME_THEMES_PATH@/default/titlebar/maximized_focus_inactive.png +titlebar_maximized_button_normal_active = @AWESOME_THEMES_PATH@/default/titlebar/maximized_normal_active.png +titlebar_maximized_button_focus_active = @AWESOME_THEMES_PATH@/default/titlebar/maximized_focus_active.png # You can use your own command to set your wallpaper wallpaper_cmd = awsetbg @AWESOME_THEMES_PATH@/default/background.png diff --git a/themes/default/titlebar/close.png b/themes/default/titlebar/close.png index b3b6398819308a3b817b76fb902ca6608e78514f..fa8a7724d760022963ae0f9bc604eabe7759415f 100644 GIT binary patch delta 40 vcmaFH^o(hO;l#+|iG~{Nt)4E9AsXi=UTzk+RqAt$0SG)@{an^LB{Ts5J+%(V delta 40 ucmaFH^o(hO;lw2x6Ag>mTRmMILo|XXUTzjR$0(}C00f?{elF{r5}E)hr42v; diff --git a/themes/default/titlebar/close_focus.png b/themes/default/titlebar/close_focus.png new file mode 100644 index 0000000000000000000000000000000000000000..a5b795849aad35f26a0386aee245f2b49a8d675c GIT binary patch literal 666 zcmV;L0%iS)P)LrSVSRJ3Y*v{1S}*~AOunfA~uR$#KKgm zQl+x8(DP3cmMDrSh=>F?>U~BroV~U;8EJ0L@vbSw1Yjf3OOVfkWu}!y){gzJxEQ z#eB{u!$W9kq!T|cXRvfY{Kb7`_y#x%)rA>oaTaR-cz1FUa4l#u$Ueu$XDZ{suI0-FQ!V`dmLv%rpv(fj6W70W>-Ia=Rgm7wkLl*ZJzL-j`*a>tzqt zK5IU;f*UM!RqacS?0hz!H$U${MLcDzVh-<6lvuCZuf9|u3 z7nN504*dDC^eeyLv)1l9k-)W)w|1MK&I{eckviSytjb3V5&h_uDn~c{Se=?KCbwyM zEWg~(4_c??mq!SkTim}qGY`6#5dKYoA>zk-ApQ@;_ZcF76#y~Z ziy$@-H-OZ**FFAUzWhHNmn{DEUnuz-NS_0y!J(hlGlYHl544~FZ)AWR5ccJ~YTnoX zp%eeZv0=r}|3LBimi)Ic!7 zWE1?#fFbC`f3UBh;Vz%||G#Y`0s|uvE(f&aKT!R9f(C;P4}6vYGF-j*|9|s3+*mvl zXhFb}_dxXqL>UY=-2XuWL%^f|iuwQl>sMf6;WVJ3e)rx3)fr%95Q2vL-bw&!{x6yJ zAMAP<=1v3}>T}~gP~HG*&LhfjpBq5K?|@whay>YFeQtoT1I{c>s^Q?Y4>2?WZ&^X2 k;q!4B3YH%&=xJ^+0CnFED5!2~q5uE@07*qoM6N<$f?snX`2YX_ literal 0 HcmV?d00001 diff --git a/themes/default/titlebar/floating_focus_inactive.png b/themes/default/titlebar/floating_focus_inactive.png new file mode 100644 index 0000000000000000000000000000000000000000..c6ac712ab6ffacd2f4f88487237b38c0aacc35bb GIT binary patch literal 414 zcmV;P0b%}$P)?+Uj>qF&D39`g z743Grn9t`}EEX7zMlem2L9MS=D;y37R_!&*~&>~>XEZzgdZ2g-@#7`xrB zfV>|J2DgRl^*VaJ-a~$gqR9MTuh#{W$pnHR{5=2E5I*yRAYcO|q9{VM*{t?b$Oh`_ z;ycY?Hk%b#mR0Q0tja7c759A~)9JJn$8n%2%JbECIvwUQ`T8B(wjs+hD*s4L)8M); ztNud2--jeg`15xsajKB2Cx0uoe@~p={!2wEc%FZ~=sTW@50!i*f&XB;yZ`_I07*qo IM6N<$f@{^f6951J literal 0 HcmV?d00001 diff --git a/themes/default/titlebar/floating_normal_active.png b/themes/default/titlebar/floating_normal_active.png new file mode 100644 index 0000000000000000000000000000000000000000..a9899991aa2e505b7a348a84b7c28f10550443a8 GIT binary patch literal 386 zcmV-|0e$|7P)F4h2(hz1F0u$ zC}YikM)9=&%o52!7nlBLV4eWMYz_a}6hzZMY0J1RB~xWO(@lebf4%QDG7sGYE76^{QgipG{&c z1J&~b4U~jpAs}Y(A~U6cgQ^7)?p#2_M3FG_B!nC=u5bq_F2i|&1_CryxgW0(0Lai0fgP6=Z1ee=216bchSNq2bGr{GWO?i=EQ9`xkJgBPEmfAFR+@#me?fRas( z638V51v2zhSJ$+c%O5|3APD3*4kbxKRaH?@6ztnD3_2w!iXs!N>zc-Kq-mNS*tRW2 zQADyVf8IdTG%CxI`o5=O7&eJI)bEO_s>+;zwr#VKLDMuT%Q9-3hPtkMAfk~Zi8e)b zT_;6R-WG8jN2m#cfJHPD*`x95BYiZ|4RDA2^E_XOW<1Zo-d}UM2Gm0=O;g4&47cOh z%O6wCxx21QaU3t4&q354GK&ko?=KJhj)>{d8s5j?c^-@6nb@RLqW9u(2KO^9%Q~O) vvp5{WJ#sy|0K4K_yMG$^X}&J{$01w+SI(v1d3~sL00000NkvXXu0mjfPWY4r literal 0 HcmV?d00001 diff --git a/themes/default/titlebar/maximized_focus_active.png b/themes/default/titlebar/maximized_focus_active.png new file mode 100644 index 0000000000000000000000000000000000000000..78a291453222dd16bf5358a1c3b607cbcf848df5 GIT binary patch literal 1013 zcmV_YnDIDh0x1W|)H}iJ{J*W}9s;s3yy z=aCWy28QYB>BnZf#ZW_)I{9JRSB7y(L_aC?tU|w1sP(O62J6e|tFPc@!&%Jc-??o( z$_?EU7(}e+)pz$qDn+y^`mw1}s9Bw~uWx|v?ps(aU09pyXl?zOj;%?2p-ON@B<`N* z36Zk8s33kwj^~eeR%6dvgDr18HjN*H?=E5}CxM||s}N|}OoW{)@8a39u;l^V zT7Q~Dgv$%2(f?*Bz3XSOTcLZrp?T`1ig9dmMQBQlfcK-hlMzA9oM~Ko*oR@Q5AKW* z%=sJ0o$Od;i4;|@Q0UGlacz&~WVk<{M+f3cyC2eLsk&!kK9s|b$-q}PN$}peVyt?6 z9?slV9GE+U<1xXwGNWLdDpj#&w4s)QG_ocNn>L8PofzDbDn-`9g^ctXao)JX{>Ne|jC_ci#3;Jojwdg`7mGIP z-)U(}Su{S}_=>D*+a3r#M_{mq?#APMxkU@k>y#}P@`I*36mr_K@liD`%W!7KkRRaV z*^BdjTdk9#p2`K#yBGRTj^a35a9u6nyLEC}0g;~5SvD`nxg%cHJ#c)~v+7p^rv#dD(b_fYZhg%cI#svrX)2lUOA5d3n}cz! zn8u8t-qTF=)J|v;F1#rE?o%PSn`hEnDO@iW8s88uCQF%0@EBM-Vbrq>FNouuMocP3 jm7*Gr=u{%7`h)!&401`p9ZAH400000NkvXXu0mjfjHK)| literal 0 HcmV?d00001 diff --git a/themes/default/titlebar/maximized_focus_inactive.png b/themes/default/titlebar/maximized_focus_inactive.png new file mode 100644 index 0000000000000000000000000000000000000000..c3f9676770133a4dd9a806ea2b240cb9527b8835 GIT binary patch literal 816 zcmV-01JC@4P)b%78FWQhbW?9;ba!ELWdK2BZ(?O2No`?gWm08fWO;GPWjp`?0=-E@ zK~y-)t(Cn?`e78s`v+?1Ws)c}q9Kw>BoGBnBuOJ`Dum`F2r5La49h~$O3|W>2!e*9 za0zPFp@QCD2oF2rkoOAEDq~woIb8|D4N+mQJ4I~l? ziU!uz)uFGi4?8N@sj2Dzz_qot*xlX5$Hxa!sT5vcUvYVP$&U;S44|^IvT$%sO${6l z2hPvWadviwi;D}y<8hpvoM3Kl4%A6bNO^fVe%|WpYBuTZ?F}z4FL-=>Wbn<+4d&

EX(#%`DvK^RX#bs}=3-?da&}!1VMq z%w{tv$2pB6U4LGIK!Cx)LDrX2AeBmaWT|SBgt{mzD=REk^aq_z$CXpdH2Va#+wBY` z-M6>5QCeDB7?^a+YTeq}3YAL5X&|ErNMMqwAn@4O7!D5)F)}j3VW-$p+oUtek~MT` zX(>N2Ee@)XMl_jBGLUpN7z`YKdcO-;e;^+GHb=cg?h_3-e(TPh2u zOOWhu2u#^+YirBjFw%<_N+OZK^Yb%eu^86Z*U{VC`wuv;&6PbZEiJsUXzh{PtE;OR uA0IF7D?q2ezaQP*-RSJ>D`e0000b%78FWQhbW?9;ba!ELWdK2BZ(?O2No`?gWm08fWO;GPWjp`?0&ht~ zK~y-)t<~L68&nv8@u!0p+Rc`&DNGQZoh)rsmW>7)V-`d+Fof9Qg3DCZ){^7@qc46*@0(+Blb1r^4?^h1IqbPxOumNs^mj4d@JHk2WH8*s@KF!X z;J-0!4`QXa2+a|k9-s1qv(PKxS74azp|9~Yh6Hw^_!#^FJQ&8kD30~hs2KR>83k9t za2;PJZ~^=lJdR=~ft8z4xxiRir2FFb2;Kv~1lw^8aSVl&m8s16;RHAbwnp(2@GjU+ zVMt=gVkji7PQ=d#e;32X7b)ik2OI-G2iv3g&sA()KW%6=9qA9g25wE_$=;H!r$2eS zw-5_p?OL}{)#&N8tPjv1ygq_qH)m)rSbKEW2Z^Ym^~6uXG#CM^vF^0AQr)}0YPvg% zVeezZ!97EB!O&W>{quz5r-0RAY^A%I^i|heVA#a)EPaaa7u|UOe}L;TynUXAm0}pS zF*M?aM#}KVfPZFrd;j}eh}SU)*6w5HG49RclPo?O!sKPYmsz^$O@Kr1;uGw}e;J}+ URCb$E@&Et;07*qoM6N<$g7W=e4gdfE literal 0 HcmV?d00001 diff --git a/themes/default/titlebar/maximized_normal_inactive.png b/themes/default/titlebar/maximized_normal_inactive.png new file mode 100644 index 0000000000000000000000000000000000000000..f3e5a82d99b29f465de7396f3b6fc5b67b1ba930 GIT binary patch literal 682 zcmV;b0#*HqP)b%78FWQhbW?9;ba!ELWdK2BZ(?O2No`?gWm08fWO;GPWjp`?0yjxS zK~y-)t(DuWsZkWgH@ROU_sIP&M6w_D1IdfLAY@aNgp?N&+pU!R+4D4Jo19bU_-tp@ zdRXQAtue=#b9sCFPs?C1kj-Y}ZM9nIWuQ{2WZ3)rJN0@!n$2dfgVky^LmQ0-_4|Dq zjYc#a4#{jb(@RQSE*C?)-7bB8elomRERtTY{~1`JP*6Ufr_<>~+wGQ?%O!O>9liu= zMIzDjV7Xk*N?WZKHJeRpx7#$COsHP3lh^AdR3d~!_gf~DQ7)IGkT8+B7^>B3 zDVxnQ^a@WT5?nr1V!Dh*BY8X?Rw|K59tQ;r?l(RH2qnV;R04|t#TkmfLw#xyrV5H9 zkqD=)(P%g%1PR~a`O{#rSj=G9fMC#@P>9aJU;rG8#hwFWa!REVmkv7s#RUit>aT%9 zy&y1D!q44qN9*;Pm0}=p0fNINcDw!7E$9wGV6@I=v*G#2sA4!SmkTTYPM;hO2X_l> z5!4Y-TPPIh>+6dShXcdU=Q9lkgZn-ur_;&aq7p&A;)mn$m{zOR4Zh#+uPt@!6by!t zDf=z3`Fzd~3pQS>R4Vo7{0l4p{sW|p_Y`&jh+tsP%YQE@4_^N0f&R<-1(B##=^-~9 Q5dZ)H07*qoM6N<$f_jiGVgLXD literal 0 HcmV?d00001 diff --git a/themes/default/titlebar/ontop_focus_active.png b/themes/default/titlebar/ontop_focus_active.png new file mode 100644 index 0000000000000000000000000000000000000000..f954bed40e4bbf0ee0ddfbcc59457e828193ea9c GIT binary patch literal 774 zcmV+h1Nr=kP)Di6WwmeK>|p#=fVEDN4~c$sas7hjX6u!g+a*lw`tB)E8<{pY}5w zjY{8W5W#w3)G2*G#m>z)huP>oOrTcIeG`Wq@-bJ2Ia|hBwS4;}wT0RQoB)dOH;U!^ zvi-L>_*g^H!CW8(NFn^Kkfm}B{jW4L*d&P90L9p}u~;R1x0RVtK!-AUE{oYJTckzK zaFd*&1`Vy(%NKs10i^ASIf}n0gSj&Kyw^1}eNE2EVmUpRWczhN7I(qcg>(qo1@F=@ z-=<-H$-?ZE)8!@D&rP0nkPiND(Dm} zIKV7{=#dza0}xRX9Ej~-KSs!P1b2}b$y0?S$!t|cq(v~A4u0*8Rl!^efgUlIFGjbe z+u3YZ#YUqHb08h&l^kAy`w)SbV%#cY^!y*vT|JwrKa>&uAQ+BAzX)~;cY%y?YXa$ZR;$z(?iPHB!)LMP5aZT8OuUr`@+2ME48du3%X(lc_z#Tv3N%;+!W^1t@SQJ zo0upRKXPSBC|)X;-KY_?2<#$oPt4fFWU;y@E~(pdQ7qpQG{^8>76YecPbglvD_5ve zY~B;|H^j6}o~f%l6}by!8OxXFr&R=Ri=`{#`zg5+ihXzFTe>M`OJ&TI{JWCjGqMln z$Z($(-?Eb!{`0rQ>b%78FWQhbW?9;ba!ELWdK2BZ(?O2No`?gWm08fWO;GPWjp`?0xC&F zK~y-)t&~Y?VnGyz{YybYmbx$sD!OnWE+pW98$rYgO+s8qg5m^%Gl~d`;z~piF;Nn; za3>mw7~;l_U>ttIX{x}c?X>!&EjXKc^}c)S-dl&oVz?9v1>|x$Sf^f(kB{(pJf{Wo zcsvve1?2O2a5$XP!EH7hMxzlvK0aVH8czofhr?JdmsqdYczAd?4OpwyqSNVMKA%&y zS}iD*%KwM^d_J1(2E14-;B-2V2MYuOTwY#6uh+w3v7lToJU>6<_4O6w@tD?i1Knt~TH*cu9kp5wrBVs$bQ*Ve zceuH^!PV6j$jnoCB9Xw?*Vh(gHk&aPIX|6FQLR>?R;#zO4+evHd3nKPGC4}0pPv{E z1~luPO?A87czSxma5!Y7e!q{mw>OX*%Ve_s4JCCVwd?hId)4iBX%eJA2cdtyG}6p= zyS-D*W|KmHH;Ty;i^WK#QmEJKJ4J3qOzGm{f;m{D(IA`6qEe~smEZ3NpU-Cww%hI0 z$u=S#kH_Q4<#Jp5q-jTa^zH2}lF20fF%$~H>-EBHHp65xArJ`AeeyjLiTs?~ee3@I z9%QbGlQ|p?7z_ql%k%Sd`jkl!5`c)96eFlaBB3VZa=EDY{%e#-T~#U-tX3-xO8kOR zzxRIu66A_ge(#lj00000NkvXXu0mjf D!Rsk0 literal 0 HcmV?d00001 diff --git a/themes/default/titlebar/ontop_normal_active.png b/themes/default/titlebar/ontop_normal_active.png new file mode 100644 index 0000000000000000000000000000000000000000..b2a216df65d978ca7b0c9d628f9e2f19f586c7cf GIT binary patch literal 565 zcmV-50?Pe~P)b%78FWQhbW?9;ba!ELWdK2BZ(?O2No`?gWm08fWO;GPWjp`?0m4Z{ zK~y-)t(09$ltC1LA9q>vBi43Bp;9a{`#^;ts4)A$G!l)FsJy5yQrrts1WAw$Tv&va zh4%$n);$Wad;^#R`-kgdXukcYP%2B(9(L5E$F>YV^5Ah&a24CjzOE)%V z&PY$nF^+G+8L$`ZIqw8<1LHczG^P(Qox^kGJqS5U8OB{`o&96ldpWwkX?%l?X zK3wm`_u$IOLNS7|RW#BrBcVmJ4HAq)tUtxoKX>0OW2|5tw8;;QO{|XNyMJBkUO%Rb z7?q5yW2|Cz3}0W?Dce1m%wnuv!YalhR!49lYx`9Sn9N`-UBEon+K~d>0vlr(a~Cj+ z`^8pkW)?4WVKR>K@M7v^oN7nBTfmq+!x+X*jEO(uBe>j-c)tf@w3Qfxm=c16a%B z4mgxWz6|c<@MDI_&uBg2=`7+(9w*wU+YtETocX^1ynB2`SY-pr00000NkvXXu0mjf D@Xr8v literal 0 HcmV?d00001 diff --git a/themes/default/titlebar/ontop_normal_inactive.png b/themes/default/titlebar/ontop_normal_inactive.png new file mode 100644 index 0000000000000000000000000000000000000000..1a06f686aceede68c701502cbe0e2d9cd104c686 GIT binary patch literal 590 zcmV-U0b%78FWQhbW?9;ba!ELWdK2BZ(?O2No`?gWm08fWO;GPWjp`?0ozGL zK~y-)tyN2_K~Wg>$|G-)cZek9nMV?Zfk%myGBGgl7#Jx7GlZYLZfoBt_g?N%=c`q+ z_gVYfYpwGgg+gNK^?K-ZIw<6>cs!0+EG93pTCGN{Rzsyy0e{Oz?D2T8UazrQt>APz z@|zu(7jIK*T!!Dh30>h_M)>4e2%fp)ts z(!%F?3%}nFyWI|(&Gvmzu~@`*yT$c-#pQAlAfZ%n|KV^zr_&L{Pn{=|Nld3x?DzYR zu-olK6e-W6)1MU%hcOzBgalHsTrM%2&4d(8&s+0?!63TbF6Q(3Tab`3%w#hElithg z^$Ig-;49GJY&I*Ml%>^bK|`64SLpS6h(@EI%?@U?TrQ*4YQ04wkq}vyOw2qopLdi> zCEf@kD}&@elCK z!KfEO!9>j-jI!Bv$U<28F;v)`0CQ>uJ@_$d*AA(M1^mW)? zd1K{LGiuak_oZ2Czx(am4@RGi2hYpZl*C(yj-5Mq;`}>SECz#}SvW2LD|3NE73nNb zu~>{0U^M|ZqDE6XnE`ix*Fh6DO6R5*=;7*|7VYp$uRC zaq<4faD8V&QJ@3@z(Zv#_(H$kJ@L`Ihu>SY-ePlu^%mz{QNAU!>7LtQFkIWY#(KQo zk!9&f2%QbC{7(b)9fEzLVHTsh)!^^CV*N{*Os7zWgabp6ffD7nxHuhPbJq3Bo zt{Zb>G+^W52EX6^m3#Icq6HNyCZe7|C&2x1Jm_C;U43-192%bo@O2d)&#E3`OqS8o5v3&R!gXQ-SWSX84@oMx9(-utsCe9@k#p1_e{DLDQt zc;!}Q)q7c!z(b&rV0vDl9;nY$+1PBKZCwZss*k5*G>AA*JwUBi=h4m4H`h-OKAh{% z3vxAmZbmJ-afiitiF(*zGuoVgx={?Udf1?!^ywviI<*e1sKtYDyHYBOmxy-Urd#XM zOZvQ0f0gCtYs6u#GQVP=5jJT>Ef%VabZZ^@^+WWM9?EWhVek;S00000 LNkvXXu0mjfSX_`J literal 0 HcmV?d00001 diff --git a/themes/default/titlebar/sticky_focus_inactive.png b/themes/default/titlebar/sticky_focus_inactive.png new file mode 100644 index 0000000000000000000000000000000000000000..d10c2b29e09320ed32a85a6571deddca5fc6f670 GIT binary patch literal 659 zcmV;E0&M+>P)b%78FWQhbW?9;ba!ELWdL_~cP?peYja~^aAhuUa%Y?FJQ@H10w765 zK~y-)rIbHz!Y~xZKNIJV6DLt~0wylN)R{{#^a9;_0ED;!8wX(K0t}tH^$Zb0EJ#&a zganZqJANIiM2VnK!IPeBC3-)9{_JOlD={9ANlMxJmghMplL@<2$1nYSdU~Rlmlqgg zV2l9~)#HA@r|ERcZUS@8p|!5T#uxyAF$SLJ;bz6g7$~J$N~@8G?gMMBYhV*vslN$K zL@g_t(7P2YrOw*$FYscqAjfe|lsS&m0yp6g4-a^LekK55?DukXIvp5eFq_R7AB{%T z@ApxbWh*N{Q4}qe#u#k3Tez-^UatqsvQBb191;frtu@NBto>}ln`#e-1J>&`vMhsT zS(mL)N1AS|d%b%78FWQhbW?9;ba!ELWdL_~cP?peYja~^aAhuUa%Y?FJQ@H10q{vg zK~y-)rIf*L6EP5mKWDwWNmEi)N{N6I7ml2`_sDB->KpMAJU|b;2^R!HK`JUODOI|= zGq!uMlPqbniHI%B)@tYT?|;TN>}qca908&AtpdJay25NHbVRuLa6uCq7F|-m{CFAo zxgFjO?m?vw2tpm|h%^yQ-hI$+aDd9yN$EG)_>b=mH*A7AVSXearRr z4Lr0=G;4FR(4tUj6%{%`yx_b;oZ`G7L7C2`+~3SsK)V6<#AAV4o25$eLM0WyW>@@~ z-Qj+FP#{}Nwdqc}p-IqP)b%78FWQhbW?9;ba!ELWdL_~cP?peYja~^aAhuUa%Y?FJQ@H10pdwS zK~y-)t&~lw>Oc^MPyfa=s9**TT!s_3Kb9W(v7>y!II;pNZc(+61eI^&*D`*PR zsV}FiPDfxM7K;TZNdjhWo_X)F-|t0Vo$lLo&hdJ^MhF2R1Tb@xH=7Ng&u8%wSO|ft zs=&-3A~16U*Sfc~AI!|C>-vY4dT@p_J-vp(dgR+*TWH7D7Ot=O~H--g_ve zAf;@4{-s(Te!pY4+re53?>!!m2fX)h zZ{lmb!i5ljTEWaHiek{0MD*)DB7*p~2{Us?5i`SDi!94JMM^0srEoYLP*v4mPenvR ze|uI$SUbwHSB=_WcU1l!CPu)>@24BUo!2%l#AB z7z1l9(lmv04$iq=5B~}rhh>aGnx>dcCK!*$y*Cd49rpKh#|0) jlH<_gA|m8@-dp