-
-
Notifications
You must be signed in to change notification settings - Fork 77
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Use clutter for the background menu #1769
Closed
Closed
Changes from all commits
Commits
Show all changes
34 commits
Select commit
Hold shift + click to select a range
b3d04cb
Prototype menu
leolost2605 efe7619
Add missing files
leolost2605 88bcd62
Add menuitems
leolost2605 c6f73c5
Allocate canvas size with actor size
leolost2605 b57ea7a
Make items selectable
leolost2605 b4d0521
Almost finished with menuitem api
leolost2605 bf1a583
Cleanup
leolost2605 1e52803
Use correct font
leolost2605 bf66104
Add separatormenuitem
leolost2605 dcef4f4
Make separator look right
leolost2605 8fa5855
Scaling works
leolost2605 e9c6956
Cleanup
leolost2605 c499ef0
Add add_separator
leolost2605 5742055
Finish background menu
leolost2605 8a8cb84
Fix scale + cleanup
leolost2605 ad17b0c
Use actor background color
leolost2605 e20c35e
Add keyboard navigation
leolost2605 4de20e7
Add keyboard navigation
leolost2605 d5fb1cd
Fix small issue
leolost2605 cc25b6a
Use MenuItem.with_label
leolost2605 a36329d
Don't use error dialogs
leolost2605 27191b0
Merge branch 'master' into clutter-desktop-menu
leolost2605 e5f8c79
Fix lint
leolost2605 f0b5fc9
Lookup colors
leolost2605 d6318c6
Update with theme
leolost2605 bd81770
Lookup color for text color
leolost2605 8250879
Fix wayland
leolost2605 f6340a4
Cleanup
leolost2605 dd188aa
More cleanup
leolost2605 fc7f5d6
Update meson.build order
leolost2605 121cae0
Fix menu position when close to monitor edges
leolost2605 cae29e3
Fix not correctly hiding the menu
leolost2605 e94192f
Merge branch 'master' into clutter-desktop-menu
lenemter e9c3a2e
Merge branch 'master' into clutter-desktop-menu
leolost2605 File filter
Filter by extension
Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,44 @@ | ||
/* | ||
* Copyright 2023 elementary, Inc. <https://elementary.io> | ||
* SPDX-License-Identifier: GPL-3.0-or-later | ||
*/ | ||
|
||
public class Gala.BackgroundMenu : Menu { | ||
public BackgroundMenu (Gala.WindowManager wm) { | ||
Object (wm: wm); | ||
} | ||
|
||
construct { | ||
var change_wallpaper = new MenuItem.with_label (_("Change Wallpaper…")); | ||
change_wallpaper.activated.connect (() => { | ||
try { | ||
AppInfo.launch_default_for_uri ("settings://desktop/appearance/wallpaper", null); | ||
} catch (Error e) { | ||
warning ("Failed to open Wallpaper Settings: %s", e.message); | ||
} | ||
}); | ||
|
||
var display_settings = new MenuItem.with_label (_("Display Settings…")); | ||
display_settings.activated.connect (() => { | ||
try { | ||
AppInfo.launch_default_for_uri ("settings://display", null); | ||
} catch (Error e) { | ||
warning ("Failed to open Display Settings: %s", e.message); | ||
} | ||
}); | ||
|
||
var system_settings = new MenuItem.with_label (_("System Settings…")); | ||
system_settings.activated.connect (() => { | ||
try { | ||
AppInfo.launch_default_for_uri ("settings://", null); | ||
} catch (Error e) { | ||
warning ("Failed to open System Settings: %s", e.message); | ||
} | ||
}); | ||
|
||
add_menuitem (change_wallpaper); | ||
add_menuitem (display_settings); | ||
add_separator (); | ||
add_menuitem (system_settings); | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change | ||||
---|---|---|---|---|---|---|
@@ -0,0 +1,233 @@ | ||||||
/* | ||||||
* Copyright 2023 elementary, Inc. <https://elementary.io> | ||||||
* SPDX-License-Identifier: GPL-3.0-or-later | ||||||
*/ | ||||||
|
||||||
public class Gala.Menu : Clutter.Actor { | ||||||
public Gala.WindowManager? wm { get; construct; } | ||||||
|
||||||
private Gala.ModalProxy modal_proxy = null; | ||||||
|
||||||
private Clutter.Actor container; | ||||||
private ShadowEffect shadow_effect; | ||||||
private Clutter.Canvas canvas; | ||||||
|
||||||
private Gtk.StyleContext style_context; | ||||||
private unowned Gtk.CssProvider? dark_style_provider = null; | ||||||
|
||||||
private MenuItem? _selected = null; | ||||||
private MenuItem? selected { | ||||||
get { | ||||||
return _selected; | ||||||
} | ||||||
set { | ||||||
if (_selected != null) { | ||||||
_selected.selected = false; | ||||||
} | ||||||
|
||||||
_selected = value; | ||||||
if (_selected != null) { | ||||||
_selected.selected = true; | ||||||
} | ||||||
} | ||||||
} | ||||||
|
||||||
public Menu (Gala.WindowManager wm) { | ||||||
Object (wm: wm); | ||||||
} | ||||||
|
||||||
construct { | ||||||
var box_layout = new Clutter.BoxLayout () { | ||||||
orientation = VERTICAL | ||||||
}; | ||||||
|
||||||
container = new Clutter.Actor () { | ||||||
layout_manager = box_layout | ||||||
}; | ||||||
|
||||||
shadow_effect = new ShadowEffect (40) { | ||||||
shadow_opacity = 200, | ||||||
css_class = "window-switcher" | ||||||
}; | ||||||
|
||||||
canvas = new Clutter.Canvas (); | ||||||
|
||||||
layout_manager = new Clutter.BinLayout (); | ||||||
add_child (container); | ||||||
add_effect (shadow_effect); | ||||||
set_content (canvas); | ||||||
|
||||||
Granite.Settings.get_default ().notify["prefers-color-scheme"].connect (() => canvas.invalidate ()); | ||||||
Gtk.Settings.get_default ().notify["gtk-theme-name"].connect (() => canvas.invalidate ()); | ||||||
|
||||||
unowned var display = wm.get_display (); | ||||||
unowned var monitor_manager = display.get_context ().get_backend ().get_monitor_manager (); | ||||||
monitor_manager.monitors_changed.connect (() => { | ||||||
scale (display.get_monitor_scale (display.get_current_monitor ())); | ||||||
}); | ||||||
scale (display.get_monitor_scale (display.get_current_monitor ())); | ||||||
|
||||||
notify["allocation"].connect (() => canvas.set_size ((int) width, (int) height)); | ||||||
|
||||||
canvas.draw.connect (draw); | ||||||
} | ||||||
|
||||||
public void add_menuitem (MenuItem menuitem) { | ||||||
container.add_child (menuitem); | ||||||
menuitem.scale (wm.get_display ().get_monitor_scale (wm.get_display ().get_current_monitor ())); | ||||||
menuitem.activated.connect (() => close_menu ()); | ||||||
|
||||||
menuitem.enter_event.connect (() => { | ||||||
selected = menuitem; | ||||||
return false; | ||||||
}); | ||||||
|
||||||
menuitem.leave_event.connect (() => { | ||||||
selected = null; | ||||||
return false; | ||||||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more.
Suggested change
|
||||||
}); | ||||||
} | ||||||
|
||||||
public void add_separator () { | ||||||
var separator = new SeparatorMenuItem (); | ||||||
container.add_child (separator); | ||||||
separator.scale (wm.get_display ().get_monitor_scale (wm.get_display ().get_current_monitor ())); | ||||||
} | ||||||
|
||||||
public void open_menu () { | ||||||
base.show (); | ||||||
|
||||||
#if HAS_MUTTER45 | ||||||
//TODO: I think that's correct but didn't test it | ||||||
Mtk.Rectangle rect; | ||||||
wm.get_display ().get_monitor_geometry (wm.get_display ().get_current_monitor (), out rect); | ||||||
#else | ||||||
var rect = wm.get_display ().get_monitor_geometry (wm.get_display ().get_current_monitor ()); | ||||||
#endif | ||||||
|
||||||
if (width + x > rect.x + rect.width) { | ||||||
x = rect.x + rect.width - width; | ||||||
} | ||||||
|
||||||
if (height + y > rect.y + rect.height) { | ||||||
y = rect.y + rect.height - height; | ||||||
} | ||||||
|
||||||
modal_proxy = wm.push_modal (this); | ||||||
} | ||||||
|
||||||
public void close_menu () { | ||||||
selected = null; | ||||||
wm.pop_modal (modal_proxy); | ||||||
|
||||||
base.hide (); | ||||||
} | ||||||
|
||||||
private void scale (float scale_factor) { | ||||||
canvas.scale_factor = scale_factor; | ||||||
shadow_effect.scale_factor = scale_factor; | ||||||
|
||||||
container.margin_top = container.margin_bottom = InternalUtils.scale_to_int (6, scale_factor); | ||||||
|
||||||
foreach (var child in container.get_children ()) { | ||||||
if (child is MenuItem) { | ||||||
((MenuItem) child).scale (scale_factor); | ||||||
continue; | ||||||
} | ||||||
|
||||||
if (child is SeparatorMenuItem) { | ||||||
((SeparatorMenuItem) child).scale (scale_factor); | ||||||
continue; | ||||||
} | ||||||
} | ||||||
} | ||||||
|
||||||
private bool draw (Cairo.Context ctx, int width, int height) { | ||||||
if (style_context == null) { // gtk is not initialized yet | ||||||
create_gtk_objects (); | ||||||
} | ||||||
|
||||||
ctx.save (); | ||||||
ctx.set_operator (Cairo.Operator.CLEAR); | ||||||
ctx.paint (); | ||||||
ctx.clip (); | ||||||
ctx.reset_clip (); | ||||||
|
||||||
if (Granite.Settings.get_default ().prefers_color_scheme == DARK) { | ||||||
unowned var gtksettings = Gtk.Settings.get_default (); | ||||||
dark_style_provider = Gtk.CssProvider.get_named (gtksettings.gtk_theme_name, "dark"); | ||||||
style_context.add_provider (dark_style_provider, Gtk.STYLE_PROVIDER_PRIORITY_APPLICATION); | ||||||
} else if (dark_style_provider != null) { | ||||||
style_context.remove_provider (dark_style_provider); | ||||||
dark_style_provider = null; | ||||||
} | ||||||
|
||||||
ctx.set_operator (Cairo.Operator.OVER); | ||||||
style_context.render_background (ctx, 0, 0, width, height); | ||||||
style_context.render_frame (ctx, 0, 0, width, height); | ||||||
ctx.restore (); | ||||||
|
||||||
return true; | ||||||
} | ||||||
|
||||||
private void create_gtk_objects () { | ||||||
var window = new Gtk.Window (); | ||||||
|
||||||
style_context = window.get_style_context (); | ||||||
style_context.add_class ("csd"); | ||||||
style_context.add_class ("unified"); | ||||||
} | ||||||
|
||||||
public override bool button_release_event (Clutter.ButtonEvent event) { | ||||||
close_menu (); | ||||||
return true; | ||||||
} | ||||||
|
||||||
#if HAS_MUTTER45 | ||||||
public override bool key_press_event (Clutter.Event event) { | ||||||
#else | ||||||
public override bool key_press_event (Clutter.KeyEvent event) { | ||||||
#endif | ||||||
switch (event.get_key_symbol ()) { | ||||||
case Clutter.Key.Up: | ||||||
cycle_menuitems (true); | ||||||
return Clutter.EVENT_STOP; | ||||||
case Clutter.Key.Down: | ||||||
cycle_menuitems (false); | ||||||
return Clutter.EVENT_STOP; | ||||||
case Clutter.Key.Escape: | ||||||
close_menu (); | ||||||
return Clutter.EVENT_PROPAGATE; | ||||||
case Clutter.Key.Return: | ||||||
if (selected != null) { | ||||||
selected.activated (); | ||||||
} | ||||||
close_menu (); | ||||||
return Clutter.EVENT_PROPAGATE; | ||||||
} | ||||||
|
||||||
return Clutter.EVENT_PROPAGATE; | ||||||
} | ||||||
|
||||||
private void cycle_menuitems (bool backwards) { | ||||||
Clutter.Actor child; | ||||||
if (selected != null) { | ||||||
if (backwards) { | ||||||
child = selected.get_previous_sibling () != null ? selected.get_previous_sibling () : container.last_child; | ||||||
} else { | ||||||
child = selected.get_next_sibling () != null ? selected.get_next_sibling () : container.first_child; | ||||||
} | ||||||
} else { | ||||||
child = backwards ? container.last_child : container.first_child; | ||||||
} | ||||||
|
||||||
while (child != null) { | ||||||
if (child is MenuItem) { | ||||||
selected = (MenuItem) child; | ||||||
break; | ||||||
} | ||||||
|
||||||
child = backwards ? child.get_previous_sibling () : child.get_next_sibling (); | ||||||
} | ||||||
} | ||||||
} |
Oops, something went wrong.
Oops, something went wrong.
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.