Skip to content

Commit

Permalink
OSX: Cleanup and get ready for this week release
Browse files Browse the repository at this point in the history
  • Loading branch information
Youssef Abou-Kewik committed Sep 30, 2019
1 parent b5e031d commit 2b91deb
Show file tree
Hide file tree
Showing 5 changed files with 214 additions and 72 deletions.
17 changes: 1 addition & 16 deletions data/ui/meldapp-ui.xml
Original file line number Diff line number Diff line change
Expand Up @@ -37,7 +37,7 @@
</menu>
<menu action="ViewMenu">
<placeholder name="ViewBarPlaceholder" />
<menuitem action="Fullscreen" />
<!--menuitem action="Fullscreen" /-->
<separator/>
<placeholder name="ViewUtilityPlaceholder" />
<separator/>
Expand All @@ -53,19 +53,4 @@
<menuitem action="Refresh" />
</menu>
</menubar>

<toolbar action="Toolbar">
<toolitem action="New"/>
<placeholder name="GeneralActions" />
<toolitem action="PrevChange"/>
<toolitem action="NextChange"/>
<toolitem action="Stop"/>
<separator/>
<placeholder name="SpecialActions" />
<separator/>
<placeholder name="FilterActions" />
</toolbar>

<popup name="Popup">
</popup>
</ui>
113 changes: 91 additions & 22 deletions meld/macwindow.py
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,10 @@
# You should have received a copy of the GNU General Public License
# along with this program. If not, see <http://www.gnu.org/licenses/>.

import ctypes
from Cocoa import NSApp
from Cocoa import NSApplicationActivateIgnoringOtherApps, NSApplicationActivateAllWindows
from AppKit import NSBundle, NSApp, NSWindow, NSAutoreleasePool, NSApplicationActivationPolicyRegular, NSApplicationActivationPolicyProhibited

from gi.repository import Gdk
from gi.repository import Gio
Expand All @@ -29,10 +32,26 @@
from meld.conf import _, ui_file
from meld.recent import recent_comparisons, RecentType

class MacWindow:
class MacWindow:
is_quartz = True

def install_mac_additions(self):
def install_mac_additions(self):

#header_bar = Gtk.Template.Child()
self.maximize_button = Gtk.Template.Child()

# Manually handle GAction additions
actions = (
("close-window", self.action_close_window),
("minimize-window", self.action_minimize_window),
("maximize-window", self.action_maximize_window),
)
for name, callback in actions:
action = Gio.SimpleAction.new(name, None)
action.connect('activate', callback)
self.add_action(action)

# Menu actions
actions = (
("FileMenu", None, _("_File")),
("New", Gtk.STOCK_NEW, _("_New Comparison…"), "<Primary>N",
Expand Down Expand Up @@ -100,15 +119,10 @@ def install_mac_additions(self):
_("Refresh the view"),
self.on_menu_refresh_activate),
)
toggleactions = (
("Fullscreen", None, _("Fullscreen"), "F11",
_("View the comparison in fullscreen"),
self.on_action_fullscreen_toggled, False),
)

self.actiongroup = Gtk.ActionGroup(name='MainActions')
self.actiongroup.set_translation_domain("meld")
self.actiongroup.add_actions(actions)
self.actiongroup.add_toggle_actions(toggleactions)

recent_action = Gtk.RecentAction(
name="Recent", label=_("Open Recent"),
Expand All @@ -127,13 +141,9 @@ def install_mac_additions(self):
self.actiongroup.get_action(menuitem).props.is_important = True
self.add_accel_group(self.ui.get_accel_group())
self.menubar = self.ui.get_widget('/Menubar')
self.toolbar = self.ui.get_widget('/Toolbar')
self.toolbar.get_style_context().add_class(
Gtk.STYLE_CLASS_PRIMARY_TOOLBAR)

self.menubar.hide()
self.quartz_ready = False
#self.connect('window_state_event', self.osx_menu_setup)

# Alternate keybindings for a few commands.
extra_accels = (
Expand All @@ -149,11 +159,12 @@ def install_mac_additions(self):
keyval, mask = Gtk.accelerator_parse(accel)
accel_group.connect(keyval, mask, 0, callback)

# Initialise sensitivity for important actions
self.actiongroup.get_action("Stop").set_sensitive(False)
# self._update_page_action_sensitivity()
self.connect('window-state-event', self.on_window_state_event)

self.appvbox.pack_start(self.menubar, False, True, 0)
def on_window_state_event(self, window, event):
# FIXME: We don't receive notification on fullscreen on OSX
# We'll have to figure this out some other way..
pass

def on_menu_file_new_activate(self, menuitem):
self.append_new_comparison()
Expand Down Expand Up @@ -243,20 +254,78 @@ def on_open_external(self, *args):
self.current_doc().open_external()

def on_toolbar_stop_clicked(self, *args):
doc = self.current_doc()
if doc.scheduler.tasks_pending():
doc.scheduler.remove_task(doc.scheduler.get_current_task())
self.current_doc().action_stop()

def action_close_window(self, *extra):
app = self.get_application()
app.quit()

def action_minimize_window(self, *extra):
# self.get_window().iconify() # Not working!
# self.iconify() # Not working!!
# window = NSApp.mainWindow() # keyWindow isn't working either!
# window.performMiniaturize_(window) # Not working!!
# window.miniaturize_(window) # Not working!!
# NSApp.miniaturizeAll_(self) # Not working!!!
# After digging, it looks like a bug in GDK where GDK_QUARTZ_BORDERLESS_WINDOW is set for our Window
# and GDK_QUARTZ_MINIATURIZABLE_WINDOW is not being set.. All because of the GtkHeaderBar.. argh.
# I'll have to fix this in the gdk code inside gtk
# self.get_window().hide() # Nope..
pass # FIXME.. This is terribly annoyting.. Highest priority for next release..

def action_maximize_window(self, *extra):
window_state = self.get_window().get_state()
is_max = window_state & Gdk.WindowState.MAXIMIZED
get_icon = Gtk.Image.new_from_icon_name
maximize_image = None
if is_max:
maximize_image = get_icon('window-maximize-symbolic', 1)
self.get_window().unmaximize()
else:
maximize_image = get_icon('window-restore-symbolic', 1)
self.get_window().maximize()
print(self.maximize_button)
# self.maximize_button.add(maximize_image)
# FIXME: Figure out how gtk ui builder works and complete this

def osx_menu_setup(self):
if self.quartz_ready == False:
self.get_application().setup_mac_integration(self.menubar)
self.quartz_ready = True

def osx_bring_to_front(self):
NSApp.deactivate()
NSApp.activateIgnoringOtherApps_(True)
NSApp.setActivationPolicy_(NSApplicationActivationPolicyRegular)
# NSApp.activateIgnoringOtherApps_(True)
# NSApp.activateWithOptions_(NSApplicationActivateIgnoringOtherApps | NSApplicationActivateAllWindows)
macapp = self.get_application()
#gtkosx_application.Application()
self.set_keep_above(True)
self.set_keep_above(False)

macapp.attention_request(gtkosx_application.ApplicationAttentionType.NFO_REQUEST)

def osx_dock_bounce(self):
macapp = gtkosx_application.Application()
macapp = self.get_application()
macapp.attention_request(gtkosx_application.ApplicationAttentionType.NFO_REQUEST)

def osx_toggle_fullscreen(self):
# FIXME: Implement
return
# handle = self.get_window_handle_helper()
# window = NSWindow.initWithWindowRef(handle) # Nope..
# window.toggleFullScreen_(None)

def _find_lib_path(self):
# FIXME: Implement
return ""

def get_window_handle_helper(self):
window = self.get_property('window')
ctypes.pythonapi.PyCapsule_GetPointer.restype = ctypes.c_void_p
ctypes.pythonapi.PyCapsule_GetPointer.argtypes = [ctypes.py_object]
gpointer = ctypes.pythonapi.PyCapsule_GetPointer(window.__gpointer__, None)
libgdk = ctypes.CDLL(self._find_lib_path() + "/libgdk-3.dylib")
libgdk.gdk_quartz_window_get_nsview.restype = ctypes.c_void_p
libgdk.gdk_quartz_window_get_nsview.argtypes = [ctypes.c_void_p]
handle = libgdk.gdk_quartz_window_get_nsview(gpointer)
return handle
61 changes: 30 additions & 31 deletions meld/meldapp.py
Original file line number Diff line number Diff line change
Expand Up @@ -188,37 +188,36 @@ def diff_files_callback(self, option, opt_str, value, parser):
parser.values.diff.append(diff_files_args)

def setup_mac_integration(self, menubar):
self.set_use_quartz_accelerators(True)
self.set_menu_bar(menubar)

item = Gtk.MenuItem.new_with_label(_("About"))
item.connect("activate", self.about_callback, None)
menubar.add(item)
self.insert_app_menu_item(item, 0)
self.set_about_item(item)

separator = Gtk.SeparatorMenuItem()
menubar.add(separator)
self.insert_app_menu_item(separator, 1)

item = Gtk.MenuItem.new_with_label(_("Preferences"))
item.connect("activate", self.preferences_callback, None)
menubar.add(item)
self.insert_app_menu_item(item, 2)

item = Gtk.MenuItem.new_with_label(_("Shell Integration"))
item.connect("activate", self.mac_shell_integration_callback, None)
menubar.add(item)
self.insert_app_menu_item(item, 3)

separator = Gtk.SeparatorMenuItem()
menubar.add(separator)
self.insert_app_menu_item(separator, 4)

self.sync_menubar()

self.ready()
self.attention_request(GtkosxApplication.ApplicationAttentionType.NFO_REQUEST)
self.set_use_quartz_accelerators(True)
self.set_menu_bar(menubar)

item = Gtk.MenuItem.new_with_label(_("About"))
item.connect("activate", self.about_callback, None)
menubar.add(item)
self.insert_app_menu_item(item, 0)
self.set_about_item(item)

separator = Gtk.SeparatorMenuItem()
menubar.add(separator)
self.insert_app_menu_item(separator, 1)

item = Gtk.MenuItem.new_with_label(_("Preferences"))
item.connect("activate", self.preferences_callback, None)
menubar.add(item)
self.insert_app_menu_item(item, 2)

item = Gtk.MenuItem.new_with_label(_("Shell Integration"))
item.connect("activate", self.mac_shell_integration_callback, None)
menubar.add(item)
self.insert_app_menu_item(item, 3)

separator = Gtk.SeparatorMenuItem()
menubar.add(separator)
self.insert_app_menu_item(separator, 4)

self.sync_menubar()

self.ready()

def parse_args(self, command_line):
usages = [
Expand Down
12 changes: 10 additions & 2 deletions meld/meldwindow.py
Original file line number Diff line number Diff line change
Expand Up @@ -43,6 +43,7 @@
from Cocoa import NSApp
from meld.macwindow import MacWindow
except Exception as ex:
print(ex)
class MacWindow:
is_quartz = False

Expand Down Expand Up @@ -148,8 +149,11 @@ def do_realize(self):

meld.ui.util.extract_accels_from_menu(menu, self.get_application())

self.osx_menu_setup()
self.osx_bring_to_front()
def do_show(self):
Gtk.ApplicationWindow.do_show(self)
if self.is_quartz:
self.osx_menu_setup()
self.osx_bring_to_front()

def _on_recentmenu_map(self, recentmenu):
for imagemenuitem in recentmenu.get_children():
Expand Down Expand Up @@ -280,6 +284,10 @@ def action_close(self, *extra):
page.on_delete_event()

def action_fullscreen_change(self, action, state):
if self.is_quartz:
self.osx_toggle_fullscreen()
return

window_state = self.get_window().get_state()
is_full = window_state & Gdk.WindowState.FULLSCREEN
action.set_state(state)
Expand Down
83 changes: 82 additions & 1 deletion meld/resources/ui/appwindow.ui
Original file line number Diff line number Diff line change
Expand Up @@ -13,8 +13,89 @@

<child type="titlebar">
<object class="GtkHeaderBar" id="header_bar">
<property name="show-close-button">true</property>
<property name="decoration-layout">close,minimize,maximize,menu:</property>
<property name="show-close-button">false</property>
<property name="visible">true</property>
<child>
<object class="GtkBox">
<property name="visible">True</property>
<property name="orientation">horizontal</property>
<property name="homogeneous">True</property>
<property name="spacing">0</property>
<child>
<object class="GtkButton" id="close_button">
<property name="action-name">win.close-window</property>
<property name="visible">true</property>
<property name="can_focus">false</property>
<property name="receives_default">false</property>
<property name="relief">none</property>
<style>
<class name="raised"/>
<class name="close"/>
</style>
<child>
<object class="GtkImage" id="close_image">
<property name="visible">true</property>
<property name="can_focus">false</property>
<property name="icon_size">1</property>
<property name="icon_name">window-close-symbolic</property>
</object>
</child>
</object>
<packing>
<property name="pack-type">start</property>
</packing>
</child>
<child>
<object class="GtkButton" id="minimize_button">
<property name="action-name">win.minimize-window</property>
<property name="visible">True</property>
<property name="can_focus">false</property>
<property name="receives_default">false</property>
<property name="relief">none</property>
<style>
<class name="raised"/>
<class name="close"/>
</style>
<child>
<object class="GtkImage" id="minimize_image">
<property name="visible">true</property>
<property name="can_focus">false</property>
<property name="icon_size">1</property>
<property name="icon_name">window-minimize-symbolic</property>
</object>
</child>
</object>
<packing>
<property name="pack-type">start</property>
</packing>
</child>
<child>
<object class="GtkButton" id="maximize_button">
<property name="action-name">win.maximize-window</property>
<property name="visible">True</property>
<property name="can_focus">false</property>
<property name="receives_default">false</property>
<property name="relief">none</property>
<style>
<class name="raised"/>
<class name="close"/>
</style>
<child>
<object class="GtkImage" id="maximize_image">
<property name="visible">true</property>
<property name="can_focus">false</property>
<property name="icon_size">1</property>
<property name="icon_name">window-maximize-symbolic</property>
</object>
</child>
</object>
<packing>
<property name="pack-type">start</property>
</packing>
</child>
</object>
</child>
<child>
<object class="GtkBox">
<property name="visible">True</property>
Expand Down

0 comments on commit 2b91deb

Please sign in to comment.