Transparent windows

Linux specific forum
Joubarbe
Enthusiast
Enthusiast
Posts: 703
Joined: Wed Sep 18, 2013 11:54 am
Location: France

Transparent windows

Post by Joubarbe »

Hello,

There are some codes on this forum to make windows transparent on Windows. I'm wondering how to do that on Linux (and OSX, to insure cross-platform compatibility). For example, the Terminal window has a transparency value.

If you have a magic code for the three OS, that'd be perfect ! :)
User avatar
RSBasic
Moderator
Moderator
Posts: 1228
Joined: Thu Dec 31, 2009 11:05 pm
Location: Gernsbach (Germany)
Contact:

Re: Transparent windows

Post by RSBasic »

Image
Image
Oma
Enthusiast
Enthusiast
Posts: 312
Joined: Thu Jun 26, 2014 9:17 am
Location: Germany

Re: Transparent windows

Post by Oma »

Hi,
thank you for your advertising, @ RSBasic :wink:

Butttt!

It only works on gtk2 because one API-Function is deprecated in gtk3.
Since V5.40 is released, i've found no simple replacement. Maybe the future or another one will do it.

Charly
PureBasic 5.4-5.7, Linux: (X/L/K)Ubuntus+Mint - Windows XP (32Bit)
PureBasic Linux-API-Library & Viewer: http://www.chabba.de
Trond
Always Here
Always Here
Posts: 7446
Joined: Mon Sep 22, 2003 6:45 pm
Location: Norway

Re: Transparent windows

Post by Trond »

A window is a widget, so you can use gtk_widget_set_opacity().

Code: Select all

ImportC ""
  gtk_widget_set_opacity(a, op.d)
EndImport

H = 350
W = 500

OpenWindow(0, 200, 300, W, H, "", #PB_Window_MaximizeGadget | #PB_Window_SizeGadget)

gtk_widget_set_opacity(WindowID(0), 0.5)

Repeat
  Event = WaitWindowEvent()
Until Event = #PB_Event_CloseWindow

User avatar
Shardik
Addict
Addict
Posts: 2058
Joined: Thu Apr 21, 2005 2:38 pm
Location: Germany

Re: Transparent windows

Post by Shardik »

Trond wrote:A window is a widget, so you can use gtk_widget_set_opacity().
That's correct but gtk_widget_set_opacity() is a relatively new function which was introduced with GTK 3.8, so it won't work with GTK 2 or GTK 3 versions older than 3.8... :wink:

But an example using the function gtk_window_set_opacity() will currently work equally well in GTK 2 and GTK 3, although it is marked as deprecated beginning with GTK 3.8:

Code: Select all

ImportC ""
  gtk_widget_is_composited(*Widget.GtkWidget)
  gtk_window_set_opacity(*Window.GtkWindow, Opacity.D)          
EndImport

OpenWindow(0, 200, 100, 300, 60, "Change window's transparency", #PB_Window_Invisible)
TrackBarGadget(0, 10, 10, 280, 20, 0, 100)
SetGadgetState(0, 0)
TextGadget(1, 15, 35, 40, 20, "0%")
TextGadget(2, 260, 35, 40, 20, "100%")

If gtk_widget_is_composited(WindowID(0)) = #False
  MessageRequester("Info", "Sorry, transparency is not supported on this system!")
  End
EndIf

HideWindow(0, #False)

Repeat
  Select WaitWindowEvent()
    Case #PB_Event_CloseWindow
      Break
    Case #PB_Event_Gadget
      If EventGadget() = 0
        gtk_window_set_opacity(WindowID(0), 1.0 - GetGadgetState(0) / 100.0)
      EndIf
  EndSelect
ForEver
Last edited by Shardik on Sun Sep 06, 2015 6:41 pm, edited 1 time in total.
Oma
Enthusiast
Enthusiast
Posts: 312
Joined: Thu Jun 26, 2014 9:17 am
Location: Germany

Re: Transparent windows

Post by Oma »

Hi there,

sorry to all, i made a mistake. I had the code with background picture in my mind. :oops:
The actual function gtk_window_set_opacity() still runs on my newest systems, but no longer (higher gtk-versions).

The linked code above isn't running on gtk3, cause some PB-structures like *gRange.GtkRange\adjustment\lower seems not or not correct filled in V5.40B1-3.

An 'home'-update is already done for gtk3 (sorry for the length)
The replacement:

Code: Select all

EnableExplicit

ImportC ""
	gtk_window_set_opacity(*window.GtkWindow, opacity.d)
	gtk_scale_clear_marks(*scale.GtkScale)
	gtk_scale_add_mark(*scale.GtkScale, value.d, position.i, *markup)
	gtk_range_get_value.d(*range.GtkRange)
	gtk_adjustment_set_lower(*adjustment.GtkAdjustment, lower.d)
	gtk_adjustment_set_value(*adjustment.GtkAdjustment, value.d)
	g_signal_connect(*instance, detailed_signal.p-ascii, *c_handler, *data, destroy= 0, flags= 0) As "g_signal_connect_data"
EndImport

; Object constants
#MainWin= 0
#TBar1    = 0

Global.i I, gEvent, gQuit, gCounter
Global *gWidget.GtkWidget, *gAdjustment.GtkAdjustment

ProcedureC Trackbar_changed(*trackbar, user_data)
	; ----- set opacity with trackbar-position ...
	gtk_widget_set_opacity(WindowID(#MainWin), gtk_range_get_value(*trackbar))
EndProcedure

If OpenWindow(#MainWin, 300, 200, 250, 200, "window-transparency", #PB_Window_SystemMenu | #PB_Window_ScreenCentered)
	TextGadget(#PB_Any, 5, 20, 90, 20, "transparency")
	TrackBarGadget(#TBar1, 90, 5, 150, 40, 0.5, 1);                    no lower-limit 0.5 possible (= 0) => need double instead PB-integer)
	
	; ----- set trackbar to adjust transparency ...
	*gWidget= GadgetID(#TBar1)
	gtk_scale_set_value_pos_(*gWidget, #GTK_POS_RIGHT);                additional display value at right side
	gtk_scale_set_draw_value_(*gWidget, #True);                        display ON
	gtk_scale_clear_marks(*gWidget);                                   no marks => wrong cause pb-int-parameter
	*gAdjustment= gtk_range_get_adjustment_(*gWidget);                 get adjustment
	gtk_adjustment_set_lower(*gAdjustment, 0.5);                       set real lower-limit to 0.5
	gtk_adjustment_set_value(*gAdjustment, 0.8);                       preset value

	For I= 5 To 10
		gtk_scale_add_mark(*gWidget, I/10, #GTK_POS_TOP, #Null)
	Next I
	
	; ----- set event for trackbar-change
 	g_signal_connect(*gWidget, "value-changed", @Trackbar_changed(), *gWidget)
 	
 	; ----- preset transparency ...
	gtk_widget_set_opacity(WindowID(#MainWin), 0.8)
	
	Repeat
		gEvent= WaitWindowEvent()
		
		Select gEvent
			Case #PB_Event_CloseWindow
				gQuit= #True
		EndSelect
		
	Until gQuit
EndIf
Regards, Charly

PS: sorry again for the posted code. Didn't see your posted codes.
Last edited by Oma on Sun Sep 06, 2015 6:53 pm, edited 3 times in total.
PureBasic 5.4-5.7, Linux: (X/L/K)Ubuntus+Mint - Windows XP (32Bit)
PureBasic Linux-API-Library & Viewer: http://www.chabba.de
Joubarbe
Enthusiast
Enthusiast
Posts: 703
Joined: Wed Sep 18, 2013 11:54 am
Location: France

Re: Transparent windows

Post by Joubarbe »

Trond wrote:A window is a widget, so you can use gtk_widget_set_opacity().

Code: Select all

ImportC ""
  gtk_widget_set_opacity(a, op.d)
EndImport

H = 350
W = 500

OpenWindow(0, 200, 300, W, H, "", #PB_Window_MaximizeGadget | #PB_Window_SizeGadget)

gtk_widget_set_opacity(WindowID(0), 0.5)

Repeat
  Event = WaitWindowEvent()
Until Event = #PB_Event_CloseWindow

This code works fine with me.

@Shardik : what's the problem exactly ?

Except that the title section is also transparent, which is not the case on the Terminal window.

(Thanks for all the answers anyway ^^)
User avatar
Shardik
Addict
Addict
Posts: 2058
Joined: Thu Apr 21, 2005 2:38 pm
Location: Germany

Re: Transparent windows

Post by Shardik »

Joubarbe wrote:If you have a magic code for the three OS, that'd be perfect ! :)
This is a cross-platform example which I tested successfully with PB 5.31 on these operating systems:
- MacOS X 10.6.8 (Snow Leopard)
- Ubuntu 14.04 x64 with KDE (tested with GTK 2 and GTK 3, tested also with PB 5.40 Beta 3 and GTK 2 and GTK 3)
- Windows XP SP3
- Windows 7 SP1 x64

Code: Select all

ImportC ""
  CompilerSelect #PB_Compiler_OS
    CompilerCase #PB_OS_Linux
      gtk_widget_is_composited(*Widget.GtkWidget)
      gtk_window_set_opacity(*Window.GtkWindow, Opacity.D)          
  CompilerEndSelect
EndImport

OpenWindow(0, 200, 100, 300, 60, "Change window's transparency",
  #PB_Window_SystemMenu | #PB_Window_Invisible)
TrackBarGadget(0, 10, 10, 280, 20, 0, 100)
SetGadgetState(0, 0)
TextGadget(1, 15, 35, 40, 20, "0%")
TextGadget(2, 260, 35, 40, 20, "100%")

CompilerSelect #PB_Compiler_OS
  CompilerCase #PB_OS_Linux
    If gtk_widget_is_composited(WindowID(0)) = #False
      MessageRequester("Info",
        "Sorry, transparency is not supported on this system!")
      End
    EndIf
  CompilerCase #PB_OS_MacOS
    Define Alpha.CGFloat
  CompilerCase #PB_OS_Windows
    SetWindowLongPtr_(WindowID(0), #GWL_EXSTYLE, #WS_EX_LAYERED)
    SetLayeredWindowAttributes_(WindowID(0), 0, 255, #LWA_ALPHA)
CompilerEndSelect

HideWindow(0, #False)

Repeat
  Select WaitWindowEvent()
    Case #PB_Event_CloseWindow
      Break
    Case #PB_Event_Gadget
      If EventGadget() = 0
        CompilerSelect #PB_Compiler_OS
          CompilerCase #PB_OS_Linux
            gtk_window_set_opacity(WindowID(0), 1.0 - GetGadgetState(0) / 100.0)
          CompilerCase #PB_OS_MacOS
            Alpha = 1.0 - GetGadgetState(0) / 100.0
            CocoaMessage(0, WindowID(0), "setAlphaValue:@", @Alpha)
          CompilerCase #PB_OS_Windows
            SetLayeredWindowAttributes_(WindowID(0), 0,
              Int(255 - GetGadgetState(0) / 100 * 255), #LWA_ALPHA)
        CompilerEndSelect
      EndIf
  EndSelect
ForEver
Joubarbe wrote:@Shardik : what's the problem exactly ?
Trond's example won't compile on Linux if you set the subsystem to GTK2 (which is the default subsystem up to PB 5.31). You can set the subsystem by clicking in the menu bar onto
Compiler => Compiler Options...
select the tab "Compiler Options" and enter the wanted subsystem behind "Library Subsystem:"

And even on not so recent Linux distributions Trond's compiled example won't run because it requires at least GTK 3.8. The current stable GTK version is 3.16.6. The optimal solution would be to query the GTK version of the Linux distribution and to use gtk_widget_set_opacity() for GTK versions beginning with 3.8 and to use gtk_window_set_opacity() for GTK versions older than 3.8... :wink:
Joubarbe
Enthusiast
Enthusiast
Posts: 703
Joined: Wed Sep 18, 2013 11:54 am
Location: France

Re: Transparent windows

Post by Joubarbe »

That is awesome ! Thanks a lot Shardik. It always feels good to have something that works on all OSs.
Post Reply