Transparent window in linux

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

Re: Transparent window in linux

Post by Oma »

Hi vwidmer,
since I included shardik's useful example in the Linux API library, I took the liberty of modifying it to change the output text via a timer event. I hope he forgives me :wink: .
I packed the necessary data into a structure, which is passed to the WidgetDrawHandler(*Widget.GtkWidget, CairoContext.I, *UserData.HUDWIN) as parameter *UserData, -> @HUD_Data.
By the structure field HUD_Data\Window with the PB-WindowNo the WidgetDrawHandler() can work window independent.
With the timer event only the structure content must be updated and WidgetDrawHandler(Window, 0, @HUD_Data) must be called manually. (Tested with PB 5.62 + PB5.70B3 for gtk3)

Code: Select all

;from shardiks example
EnableExplicit

#CAIRO_OPERATOR_SOURCE = 1

ImportC ""
	gdk_cairo_create(*Drawable.GdkDrawable)
	gtk_widget_get_window(*Widget.GtkWidget)
	gtk_widget_is_composited(*Widget.GtkWidget)
EndImport

ImportC "-lcairo"
	cairo_paint(*CairoContext)
	cairo_set_operator(*CairoContext, CairoOperator.I)
	cairo_set_source_rgba(*CairoContext, Red.D, Green.D, Blue.D, Alpha.D)
EndImport

ImportC ""
	gdk_screen_get_rgba_visual(*Screen.GdkScreen)
	gdk_screen_get_system_visual(*Screen.GdkScreen)
	gtk_widget_set_visual(*Vidget.GtkWidget, *Visual.GdkVisual)
EndImport

; Object constants
;Window ...
#Win_Main  = 0
;Gadgets ...
#ImgGdgt   = 0

Define Container.I
Define Screen.I
Define Visual.I
Define Window.I

Structure HUDWIN
	Window.i
	Counter.i
	RumourBasic.s
	Rumour.s
	Exit.s
EndStructure
Global HUD_Data.HUDWIN
With HUD_Data
	\Counter    = 0
	\RumourBasic= "Text in HUD window"
	\Rumour     = \RumourBasic
	\Exit       = "<Esc> to close"
EndWith

ProcedureC WidgetDrawHandler(*Widget.GtkWidget, CairoContext.I, *UserData.HUDWIN)
	CairoContext = gdk_cairo_create(gtk_widget_get_window(*Widget))
	cairo_set_source_rgba(CairoContext, 1, 1, 1, 0)
	cairo_set_operator(CairoContext, #CAIRO_OPERATOR_SOURCE)
	cairo_paint(CairoContext)
	
	If StartDrawing(WindowOutput(HUD_Data\Window))
		; ----- Draw frame of HUD
		DrawingMode(#PB_2DDrawing_Default)
		Line(1, 1, WindowWidth(HUD_Data\Window), 1, $FF)
		Line(1, 2, WindowWidth(HUD_Data\Window), 1, $FF)
		Line(1, WindowHeight(HUD_Data\Window), WindowWidth(HUD_Data\Window), 1, $FF)
		Line(1, WindowHeight(HUD_Data\Window) - 1, WindowWidth(HUD_Data\Window), 1, $FF)
		Line(1, 1, 1, WindowHeight(HUD_Data\Window), $FF)
		Line(2, 1, 1, WindowHeight(HUD_Data\Window), $FF)
		Line(WindowWidth(HUD_Data\Window), 1, 1, WindowHeight(HUD_Data\Window) - 1, $FF)
		Line(WindowWidth(HUD_Data\Window) - 1, 1, 1, WindowHeight(HUD_Data\Window) - 2, $FF)
		
		; ----- Draw text into HUD window
		DrawingMode(#PB_2DDrawing_Transparent)
		DrawText((WindowWidth(HUD_Data\Window) - TextWidth(*UserData\Rumour)) / 2, 26, *UserData\Rumour, $FF0000)
		DrawText(48, 53, *UserData\Exit, $FF)
		StopDrawing()
	EndIf
EndProcedure

CreateImage(#ImgGdgt, 220, 100, 32, #PB_Image_Transparent)
Window = OpenWindow(#Win_Main, 200, 150, ImageWidth(#ImgGdgt), ImageHeight(#ImgGdgt), "HUD window", #PB_Window_Invisible)

HUD_Data\Window= #Win_Main

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

; ----- Disable visibility of window frame
; gtk_window_set_decorated_(Window, #False)

; ----- Enable modification of window colors
gtk_widget_set_app_paintable_(Window, #True)

ImageGadget(#ImgGdgt, 0, 0, ImageWidth(#ImgGdgt), ImageHeight(#ImgGdgt), ImageID(#ImgGdgt))

; ----- Delete GdkWindow resources to be able to change colormap
gtk_widget_unrealize_(Window)

; ----- Get window's child container
Container = g_list_nth_data_(gtk_container_get_children_(gtk_bin_get_child_(WindowID(#Win_Main))), 0)

g_signal_connect_(GadgetID(#ImgGdgt), "draw", @WidgetDrawHandler(), @HUD_Data)
Screen = gtk_widget_get_screen_(Window)
Visual = gdk_screen_get_rgba_visual(Screen)

If Visual = 0
	Visual = gdk_screen_get_system_visual(Screen)
EndIf

gtk_widget_set_visual(Window, Visual)

; ----- Realize window and rebuild new GdkWindow
HideWindow(#Win_Main, #False)

; ----- Define <Esc> key to close splash window
AddKeyboardShortcut(#Win_Main, #PB_Shortcut_Escape, 0)

AddWindowTimer(#Win_Main, 999, 1000)

Repeat
	Select WaitWindowEvent()
		Case #PB_Event_CloseWindow
			Break
		Case #PB_Event_Menu
			If EventMenu() = 0
				Break
			EndIf
		Case #PB_Event_Timer
			HUD_Data\Counter+ 1
			HUD_Data\Rumour= HUD_Data\RumourBasic + " " + Str(HUD_Data\Counter)
    	WidgetDrawHandler(Window, #Null, @HUD_Data)
	EndSelect
ForEver
Regards, Charly
PureBasic 5.4-5.7, Linux: (X/L/K)Ubuntus+Mint - Windows XP (32Bit)
PureBasic Linux-API-Library & Viewer: http://www.chabba.de
User avatar
Shardik
Addict
Addict
Posts: 1989
Joined: Thu Apr 21, 2005 2:38 pm
Location: Germany

Re: Transparent window in linux

Post by Shardik »

vwidmer wrote:I am trying the example with the text but I cant get it to change correctly it just keeps drawing on top of it self. I am not clear on what you mean by "define the text in this procedure dynamically using a Shared string variable"
Thank you Charly for the sophisticated extention of my example. Nevertheless I also want to demonstrate what I proposed by using a Shared string variable although Charly's approach is more flexible and therefore should be preferred... :wink:

In my modified example I added the declaration of the new string variable HUDText and in the procedure WidgetDrawHandler() I also added the definition of the Shared string variable HUDText (of course I also could have declared HUDText as global but global variables should be avoided). Now in the procedure WidgetDrawHandler() the content of HUDText is parsed (the 2 lines are separated by a linefeed) by StringField() and displayed. I have also used a timer like Charly. This timer counts down from 10 to 0, the remaining seconds are displayed in the HUD window and when reaching 0 the HUD window is closed (alternatives for immediate closing are pressing the escape key or closing the HUD window with the x-button in the title line).

In order to change the displayed HUD text, you have to call WidgetDrawHandler() by yourself after changing the content of HUDText with

Code: Select all

WidgetDrawHandler(Window, 0, 0)

Code: Select all

EnableExplicit

#CAIRO_OPERATOR_SOURCE = 1

ImportC ""
  gdk_cairo_create(*Drawable.GdkDrawable)
  gtk_widget_get_window(*Widget.GtkWidget)
  gtk_widget_is_composited(*Widget.GtkWidget)
EndImport

ImportC "-lcairo"
  cairo_paint(*CairoContext)
  cairo_set_operator(*CairoContext, CairoOperator.I)
  cairo_set_source_rgba(*CairoContext, Red.D, Green.D, Blue.D, Alpha.D)
EndImport

ImportC ""
  gdk_screen_get_rgba_visual(*Screen.GdkScreen)
  gdk_screen_get_system_visual(*Screen.GdkScreen)
  gtk_widget_set_visual(*Vidget.GtkWidget, *Visual.GdkVisual)
EndImport

Define Container.I
Define CountDownSeconds.I
Define HUDText.S
Define Screen.I
Define Visual.I
Define Window.I

ProcedureC WidgetDrawHandler(*Widget.GtkWidget, CairoContext.I, *UserData)
  Shared HUDText.S

  CairoContext = gdk_cairo_create(gtk_widget_get_window(*Widget))
  cairo_set_source_rgba(CairoContext, 1, 1, 1, 0)
  cairo_set_operator(CairoContext, #CAIRO_OPERATOR_SOURCE)
  cairo_paint(CairoContext)

  If StartDrawing(WindowOutput(0))
    ; ----- Draw frame of HUD
    DrawingMode(#PB_2DDrawing_Default)
    Line(1, 1, WindowWidth(0), 1, $FF)
    Line(1, 2, WindowWidth(0), 1, $FF)
    Line(1, WindowHeight(0), WindowWidth(0), 1, $FF)
    Line(1, WindowHeight(0) - 1, WindowWidth(0), 1, $FF)
    Line(1, 1, 1, WindowHeight(0), $FF)
    Line(2, 1, 1, WindowHeight(0), $FF)
    Line(WindowWidth(0), 1, 1, WindowHeight(0) - 1, $FF)
    Line(WindowWidth(0) - 1, 1, 1, WindowHeight(0) - 2, $FF)

    ; ----- Draw text into HUD window
    DrawingMode(#PB_2DDrawing_Transparent)
    DrawText(10, 26, StringField(HUDText, 1, #LF$), $FF0000)
    DrawText(32, 53, StringField(HUDText, 2, #LF$), $FF)
    StopDrawing()
  EndIf
EndProcedure

CreateImage(0, 240, 100, 32, #PB_Image_Transparent)
Window = OpenWindow(0, 500, 150, ImageWidth(0), ImageHeight(0),
  "HUD window", #PB_Window_Invisible)

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

; ----- Disable visibility of window frame
; gtk_window_set_decorated_(Window, #False)

; ----- Enable modification of window colors
gtk_widget_set_app_paintable_(Window, #True)

ImageGadget(0, 0, 0, ImageWidth(0), ImageHeight(0), ImageID(0))

; ----- Delete GdkWindow resources to be able to change colormap
gtk_widget_unrealize_(Window)

; ----- Get window's child container
Container = g_list_nth_data_(gtk_container_get_children_(0 +
  gtk_bin_get_child_(WindowID(0))), 0)

g_signal_connect_(GadgetID(0), "draw", @WidgetDrawHandler(), 0)
Screen = gtk_widget_get_screen_(Window)
Visual = gdk_screen_get_rgba_visual(Screen)
   
If Visual = 0
  Visual = gdk_screen_get_system_visual(Screen)
EndIf

gtk_widget_set_visual(Window, Visual)

; ----- Realize window and rebuild new GdkWindow
HideWindow(0, #False)

; ----- Define <Esc> key to close splash window
AddKeyboardShortcut(0, #PB_Shortcut_Escape, 0)

; ----- Set timer for countdown
CountDownSeconds = 10
AddWindowTimer(0, 0, 1000)

; ----- Set HUD text
HUDText = "Closing HUD in " + Str(CountDownSeconds) + " seconds" +
  #LF$ + "<Esc> To close now"

Repeat
  Select WaitWindowEvent()
    Case #PB_Event_CloseWindow
      Break
    Case #PB_Event_Menu
      If EventMenu() = 0
        Break
      EndIf
    Case #PB_Event_Timer
      CountDownSeconds - 1

      If CountDownSeconds = 0
        CloseWindow(0)
        Break
      Else
        HUDText = "Closing HUD in " + Str(CountDownSeconds) + " seconds" +
          #LF$ + "<Esc> to close now"
        WidgetDrawHandler(Window, 0, 0)
      EndIf
  EndSelect
ForEver
vwidmer
Enthusiast
Enthusiast
Posts: 282
Joined: Mon Jan 20, 2014 6:32 pm

Re: Transparent window in linux

Post by vwidmer »

Thanks for the examples.. you guys are awesome thanks again.
WARNING: I dont know what I am doing! I just put stuff here and there and sometimes like magic it works. So please improve on my code and post your changes so I can learn more. TIA
vwidmer
Enthusiast
Enthusiast
Posts: 282
Joined: Mon Jan 20, 2014 6:32 pm

Re: Transparent window in linux

Post by vwidmer »

Is there a setting or way to make the transparency click through?

like now if u click somewhere in the transparent area it doesnt click whats under it.

Thanks
WARNING: I dont know what I am doing! I just put stuff here and there and sometimes like magic it works. So please improve on my code and post your changes so I can learn more. TIA
ccode
User
User
Posts: 99
Joined: Sat Jun 23, 2018 5:21 pm

Re: Transparent window in linux

Post by ccode »

vwidmer wrote:Is there a setting or way to make the transparency click through?

like now if u click somewhere in the transparent area it doesnt click whats under it.
How do you mean ?

A click event in the window works in the transparent area (of the image). (Or does not work?)
All you have to do is paint your GUI elements on the image and get the coordinates.
Or what do you want to achieve?
vwidmer
Enthusiast
Enthusiast
Posts: 282
Joined: Mon Jan 20, 2014 6:32 pm

Re: Transparent window in linux

Post by vwidmer »

Sorry for not being clear.

What I mean is lets say is if I have the transparent window say over the [X] (for closing a window) of another window and I click in the transparent area I it selects the transparent app it does not click through to the window [X] under it.

I dont know the correct term but yes the window is transparent but its still there.

thanks
WARNING: I dont know what I am doing! I just put stuff here and there and sometimes like magic it works. So please improve on my code and post your changes so I can learn more. TIA
Oma
Enthusiast
Enthusiast
Posts: 312
Joined: Thu Jun 26, 2014 9:17 am
Location: Germany

Re: Transparent window in linux

Post by Oma »

The transparency concerns only the display, the window area (and thus the action area) remains unaffected by this rectangular and on top.
I don't know any commands and haven't yet seen a simple procedure that forwards actions such as mouse clicks on transparent parts to underlying objects.
I don't mean to say it's not possible, but I could only do it in an extremely complex way.

Regards, Charly
PureBasic 5.4-5.7, Linux: (X/L/K)Ubuntus+Mint - Windows XP (32Bit)
PureBasic Linux-API-Library & Viewer: http://www.chabba.de
Post Reply