shoes / shoes4

Shoes 4 : the next version of Shoes
Other
1.59k stars 194 forks source link

Is it possible to make custom titlebars? #1543

Closed pedrozath closed 6 years ago

pedrozath commented 6 years ago

I'm trying to achieve this look:

screen shot 2018-01-16 at 09 10 43

(source: http://robin.github.io/cocoa/mac/2016/03/28/title-bar-and-toolbar-showcase/)

I've tried many ways, but couldn't even find out how to do that in SWT. So before giving up, would like to consult the experts here for help. Any clues?

Thanks in advance!

pedrozath commented 6 years ago

So after +10h digging into Shoes source, SWT source and Cocoa reference, I was finally able to do it

This is how I've accomplished it, placing this code right before my Shoes app declaration:

class Shoes
  module Swt
    class App
      def initialize_shell
        @image = ::Swt::Graphics::Image.new(::Swt.display, ICON)
        @shell = ::Swt::Widgets::Shell.new(::Swt.display, main_window_style)
        @shell.image = @image
        @shell.text = @dsl.app_title
        @shell.background_mode = ::Swt::SWT::INHERIT_DEFAULT
        @shell.background = @background.real

        full_size_byte_mask = 32768
        hack_cocoa_main_window('setTitleVisibility:', 1)
        hack_cocoa_main_window('setStyleMask:', @shell.view.window.styleMask | full_size_byte_mask)
        hack_cocoa_main_window('setTitlebarAppearsTransparent:', 1)
      end

      private

      def hack_cocoa_main_window(key, value, type=nil)
        key = org.eclipse.swt.internal.cocoa::OS.sel_registerName(key)
        id  = @shell.view.window.id
        org.eclipse.swt.internal.cocoa::OS.objc_msgSend(id, key, value)
      end
    end
  end
end

It's a very ugly hack, but since SWT doesn't offer any alternative for this features yet, ima use it for a while.

jasonrclark commented 6 years ago

Ugly yes, but impressive digging! Also, greatly appreciate you sharing it for reference so if others have OS-specific fiddling they've got somewhere to start.

FWIW, my only other thought here is that it might be slightly more future-proof to us changing things in initialize_shell if you alias method chained or Module#prepend to get your hacks spliced in.

pedrozath commented 6 years ago

Thanks a lot @jasonrclark. Here's how it turned out for now:

module TransparentTitleBar
  def initialize_shell
    super
    hack_cocoa_main_window('setTitleVisibility:', 1)
    full_size_content_view_byte_mask = 32768
    style_mask = @shell.view.window.styleMask | full_size_content_view_byte_mask
    hack_cocoa_main_window('setStyleMask:', style_mask)
    hack_cocoa_main_window('setTitlebarAppearsTransparent:', 1)
  end

  private

  def hack_cocoa_main_window(key, value, type=nil)
    key = org.eclipse.swt.internal.cocoa::OS.sel_registerName(key)
    id  = @shell.view.window.id
    org.eclipse.swt.internal.cocoa::OS.objc_msgSend(id, key, value)
  end
end

Shoes::Swt::App.send(:prepend, TransparentTitleBar)