Detecting left mouse click outside window

Just starting out? Need help? Post your questions and find answers here.
User avatar
moulder61
Enthusiast
Enthusiast
Posts: 205
Joined: Sun Sep 19, 2021 6:16 pm
Location: U.K.

Detecting left mouse click outside window

Post by moulder61 »

Hi all,
I'm trying to create my own logout dialog for Linux. It shows a small version of my wallpaper and 3 buttons for Logout, Restart and Shutdown.

Image

I programmed it to have no title bar, not show up in the taskbar and have no Cancel option. So, apart from pressing the ESC key I want to be able to close the window by left clicking anywhere outside of it. So far, I can't work out how to do it. Maybe it's not possible?
The closest I got was clicking inside the window then moving the mouse outside the window and it closes, because I can work out how to detect a left click and then the mouse being outside the window, but that's not the effect I'm after.
I can also get it to close if I click in the window itself but not on the buttons, but again, that's not what I'm after exactly.
The question is basically, how do I detect a mouse click outside a window?
I could just add a Cancel button, but I'm awkward and like to do things the hard way. 8)
Any ideas?

Thanks,
Moulder.
"If it ain't broke, fix it until it is!

This message is brought to you thanks to SenselessComments.com

My PB stuff for Linux: "https://u.pcloud.link/publink/show?code ... z3MR0T3jyV
Axolotl
Addict
Addict
Posts: 872
Joined: Wed Dec 31, 2008 3:36 pm

Re: Detecting left mouse click outside window

Post by Axolotl »

If you want close your app by that click you can wait for an

Code: Select all

case #PB_Event_DeactivateWindow 
event and leave the mainloop (End the app!).
Just because it worked doesn't mean it works.
PureBasic 6.04 (x86) and <latest stable version and current alpha/beta> (x64) on Windows 11 Home. Now started with Linux (VM: Ubuntu 22.04).
User avatar
moulder61
Enthusiast
Enthusiast
Posts: 205
Joined: Sun Sep 19, 2021 6:16 pm
Location: U.K.

Re: Detecting left mouse click outside window

Post by moulder61 »

Thanks for the pointer, Axolotl.
Whether I can work out how to actually do that remains to be seen! :)
I noticed you made another post after replying to this one regarding "Return-Values of WindowMouseX() and WindowMouseY()".
Is that related to my question? If so, are you suggesting that I couldn't do it the way I wanted because of a possible bug?

Moulder.
"If it ain't broke, fix it until it is!

This message is brought to you thanks to SenselessComments.com

My PB stuff for Linux: "https://u.pcloud.link/publink/show?code ... z3MR0T3jyV
User avatar
moulder61
Enthusiast
Enthusiast
Posts: 205
Joined: Sun Sep 19, 2021 6:16 pm
Location: U.K.

Re: Detecting left mouse click outside window

Post by moulder61 »

@Axolotl,

I just looked at your other post and you have included the necessary code to quit when the window is deactivated.
It never occurred to me to do it that way so thanks for that. ;)

Moulder.
"If it ain't broke, fix it until it is!

This message is brought to you thanks to SenselessComments.com

My PB stuff for Linux: "https://u.pcloud.link/publink/show?code ... z3MR0T3jyV
Axolotl
Addict
Addict
Posts: 872
Joined: Wed Dec 31, 2008 3:36 pm

Re: Detecting left mouse click outside window

Post by Axolotl »

Hi Moulder,

yes, that other post is because I was thinking about a solution for your problem. I know you are on linux, so I checked something out.
My first idea was to use a window with the desktop size, so mouse clicks are always inside.
But than I remembered that I have no idea how to create transparent screens on linux..... (You should know I am just started my linux adventure)
Instead of leaving the mainloop you can hide the window and by using a timer bring the window back.... (but that is not what you are after I guess)
Just because it worked doesn't mean it works.
PureBasic 6.04 (x86) and <latest stable version and current alpha/beta> (x64) on Windows 11 Home. Now started with Linux (VM: Ubuntu 22.04).
User avatar
moulder61
Enthusiast
Enthusiast
Posts: 205
Joined: Sun Sep 19, 2021 6:16 pm
Location: U.K.

Re: Detecting left mouse click outside window

Post by moulder61 »

Hi Axolotl,
I did another version using a full screen and sprites which worked OK.
I wanted to experiment with buttons/gadgets to see if I could do it but it was more trouble.
Your solution worked, mostly. My problem is that I'm using a minimal environment which doesn't have a desktop as such, so clicking outside the window on the desktop doesn't take focus away from the window(deactivate it), so I had to come up with a workaround using xdotool. :) I did say I was awkward! Clicking on another window, however, did change the focus so that worked as expected.
I don't think individual transparent screens are possible unless you use some kind of compositor like Picom maybe? Not sure?
The way I did it(regarding the sprite based logout application) was to take a screenshot of my desktop using either imagemagick or scrot(scrot was slightly slower) shrink it and blow it back up and display that image in the main window in an attempt to do a kind of fake blurring behind the logout window.

Image

It works quite well. Just not as slick as BetterLockScreen though.
When I clean up both versions I'll share them on here so people can laugh or cry. Whatever. :oops:

Moulder.
"If it ain't broke, fix it until it is!

This message is brought to you thanks to SenselessComments.com

My PB stuff for Linux: "https://u.pcloud.link/publink/show?code ... z3MR0T3jyV
mestnyi
Addict
Addict
Posts: 1102
Joined: Mon Nov 25, 2013 6:41 am

Re: Detecting left mouse click outside window

Post by mestnyi »

Code: Select all

Global w_this, w_flag
DisableDebugger

Enumeration #PB_EventType_FirstCustomValue
  #PB_eventtype_Left2Click
  #PB_eventtype_Left3Click
EndEnumeration

Procedure SetGadgetState_(gadget, state)
    CompilerSelect #PB_Compiler_OS
      CompilerCase #PB_OS_MacOS
       ; ExplorerListGadget, ListIconGadget и ListViewGadget — все три построены на одном и том же классе Cocoa (NSTableView).
       ; CocoaMessage(0, GadgetID(gadget), "scrollColumnToVisible:", state)
        If state >= 0
          CocoaMessage(0, GadgetID(gadget), "scrollRowToVisible:", state )
        EndIf
        
      CompilerCase #PB_OS_Windows
				Select GadgetType(gadget)
					Case #PB_GadgetType_ListView
						SendMessage_(GadgetID(gadget), #LB_SETTOPINDEX, CountGadgetItems(gadget) - 1, #Null)
					Case #PB_GadgetType_ListIcon
						SendMessage_(GadgetID(gadget), #LVM_ENSUREVISIBLE, CountGadgetItems(gadget) - 1, #Null)
					Case #PB_GadgetType_Editor
						SendMessage_(GadgetID(gadget), #EM_SCROLLCARET, #SB_BOTTOM, 0)
				EndSelect
				
			CompilerCase #PB_OS_Linux
				Protected *Adjustment.GtkAdjustment
				*Adjustment = gtk_scrolled_window_get_vadjustment_(gtk_widget_get_parent_(GadgetID(gadget)))
				*Adjustment\value = *Adjustment\upper
				gtk_adjustment_value_changed_(*Adjustment)
		CompilerEndSelect 
		
    SetGadgetState(gadget, state)
  EndProcedure
  
  Procedure DoEvents( EventType )
  Protected result
  
  Select EventType
    Case #PB_EventType_LeftButtonDown : result = 1 : AddGadgetItem(w_flag, -1, " leftdown")
    Case #PB_EventType_LeftButtonUp   : result = 1 : AddGadgetItem(w_flag, -1, "  leftup")
    Case #PB_EventType_LeftClick      : result = 1 : AddGadgetItem(w_flag, -1, "   click") 
    Case #PB_eventtype_Left2Click     : result = 1 : AddGadgetItem(w_flag, -1, "     2_click") 
    Case #PB_eventtype_Left3Click     : result = 1 : AddGadgetItem(w_flag, -1, "       3_click") 
  EndSelect
  
  If result
    SetGadgetState(w_flag, CountGadgetItems(w_flag) - 1)
  EndIf
EndProcedure

Procedure MouseState( )
  Static press.b, ClickTime.q, ClickCount
  Protected DoubleClickTime, ElapsedMilliseconds.q, state.b
  
  CompilerSelect #PB_Compiler_OS 
    CompilerCase #PB_OS_Linux
      Protected desktop_x, desktop_y, handle, *GdkWindow.GdkWindowObject = gdk_window_at_pointer_( @desktop_x, @desktop_y )
      
      If *GdkWindow
        gdk_window_get_pointer_(*GdkWindow, @desktop_x, @desktop_y, @mask)
      EndIf
      
      If mask & 256; #GDK_BUTTON1_MASK
        state = 1
      EndIf
      If mask & 512 ; #GDK_BUTTON3_MASK
        state = 3
      EndIf
      If mask & 1024 ; #GDK_BUTTON2_MASK
        state = 2
      EndIf
      
    CompilerCase #PB_OS_Windows
      state = GetAsyncKeyState_(#VK_LBUTTON) >> 15 & 1 + 
              GetAsyncKeyState_(#VK_RBUTTON) >> 15 & 2 + 
              GetAsyncKeyState_(#VK_MBUTTON) >> 15 & 3 
    CompilerCase #PB_OS_MacOS
       ;EnableDebugger
       state = CocoaMessage(0, 0, "NSEvent pressedMouseButtons") ; class var pressedMouseButtons: Int { get }
       ;Debug CocoaMessage(0, 0, "buttonNumber") ; var buttonNumber: Int { get }
       ;Debug CocoaMessage(0, 0, "clickCount") ; var clickCount: Int { get }
  CompilerEndSelect
  
  If press <> state
    If state
      ElapsedMilliseconds.q = ElapsedMilliseconds( ) 
      
      CompilerIf #PB_Compiler_OS = #PB_OS_Windows
        DoubleClickTime = 10
      CompilerElse
        DoubleClickTime = DoubleClickTime( )
      CompilerEndIf
      
      If DoubleClickTime > ( ElapsedMilliseconds - ClickTime )
        ClickCount + 1
      Else
        ClickCount = 1
      EndIf
      ClickTime = ElapsedMilliseconds
      
      If ClickCount = 1
        If state = 1
          Debug "LeftDown - "
          DoEvents( #PB_EventType_LeftButtonDown )
        ElseIf state = 2
          Debug "RightDown - "
        EndIf
      EndIf
      
    Else
      If ClickCount = 1
        If press = 1
          Debug "LeftUp - "
          DoEvents( #PB_EventType_LeftButtonUp )
        ElseIf press = 2
          Debug "RightUp - "
        EndIf
      EndIf
      
      ;\\ do 3click events
      If ClickCount = 3
        If press = 1
          Debug "   Left3Click - "
          DoEvents( #PB_eventtype_Left3Click )
        ElseIf press = 2
          Debug "   Right3Click - "
        EndIf
        
        ;\\ do 2click events
      ElseIf ClickCount = 2
        If press = 1
          Debug "  Left2Click - "
          DoEvents( #PB_eventtype_Left2Click )
        ElseIf press = 2
          Debug "  Right2Click - "
        EndIf
        
        
        ;\\ do 1click events
      Else
        ;         If Not PressedWidget( )\state\drag
        ;           If PressedWidget( ) = EnteredWidget( )
        If press = 1
          Debug " LeftClick - "
          DoEvents( #PB_EventType_LeftClick )
        ElseIf press = 2
          Debug " RightClick - "
        EndIf
        
        ;           EndIf
        ;         EndIf
      EndIf
      
    EndIf
    press = state
  EndIf
  
EndProcedure


OpenWindow(0, 0, 0, 170, 300, "click-events", #PB_Window_SystemMenu | #PB_Window_ScreenCentered)
w_flag = ListViewGadget(-1,10, 10, 150, 200) 
w_this = ButtonGadget(-1,10, 220, 150, 70, "Click me", #PB_Button_MultiLine )


Repeat
  Event = WaitWindowEvent(1)
  MouseState( )
  
Until Event = #PB_Event_CloseWindow
Last edited by mestnyi on Wed Oct 09, 2024 6:34 pm, edited 1 time in total.
User avatar
moulder61
Enthusiast
Enthusiast
Posts: 205
Joined: Sun Sep 19, 2021 6:16 pm
Location: U.K.

Re: Detecting left mouse click outside window

Post by moulder61 »

Hi mestnyi,

I'm not sure what your code is for exactly but it doesn't solve the issue I had because it doesn't detect mouse clicks outside the window. At least not in Linux.

Thanks anyway.
Moulder.
"If it ain't broke, fix it until it is!

This message is brought to you thanks to SenselessComments.com

My PB stuff for Linux: "https://u.pcloud.link/publink/show?code ... z3MR0T3jyV
RASHAD
PureBasic Expert
PureBasic Expert
Posts: 4991
Joined: Sun Apr 12, 2009 6:27 am

Re: Detecting left mouse click outside window

Post by RASHAD »

Use Thread
Egypt my love
User avatar
moulder61
Enthusiast
Enthusiast
Posts: 205
Joined: Sun Sep 19, 2021 6:16 pm
Location: U.K.

Re: Detecting left mouse click outside window

Post by moulder61 »

Hi RASHAD,

As one of the acknowledged experts on here, "Use Thread" might well be the answer, but I have no idea what that means?

Moulder.
"If it ain't broke, fix it until it is!

This message is brought to you thanks to SenselessComments.com

My PB stuff for Linux: "https://u.pcloud.link/publink/show?code ... z3MR0T3jyV
RASHAD
PureBasic Expert
PureBasic Expert
Posts: 4991
Joined: Sun Apr 12, 2009 6:27 am

Re: Detecting left mouse click outside window

Post by RASHAD »

Hi
I am not expert with Linux :)
But I hope the next snippet will help somehow
Good luck
Remember to enable thread safe in compiler options

Code: Select all

Global Quit,active

Procedure watchdog(par)
  Repeat
    Delay(25)
    If active = 1
      active = 0
      Debug "Mouse clicked outside"
    EndIf  
  Until Quit = 1
EndProcedure

If OpenWindow(0, 0, 0, 195, 260, "PureBasic Window", #PB_Window_SystemMenu | #PB_Window_MinimizeGadget | #PB_Window_MaximizeGadget|#PB_Window_ScreenCentered)
ButtonGadget(0,10,10,80,30,"EXIT")  
  
Thread = CreateThread(@watchDOG(),30)
  Repeat
    Select WaitWindowEvent(1)
      Case #PB_Event_CloseWindow
        Quit = 1
        
      Case #PB_Event_DeactivateWindow 
        active = 1
        
      Case #PB_Event_Gadget
        Select EventGadget()
          Case 0
            Quit = 1
        EndSelect
    EndSelect
  Until Quit = 1  
EndIf
End   
Egypt my love
User avatar
moulder61
Enthusiast
Enthusiast
Posts: 205
Joined: Sun Sep 19, 2021 6:16 pm
Location: U.K.

Re: Detecting left mouse click outside window

Post by moulder61 »

@RASHAD

I managed to get my application working using Axolotl's example by adding these lines:

Select event
Case #PB_Event_DeactivateWindow
End

One of the problems I have, as I kind of explained before somewhere, is that I am not using your average Ubuntu or Debian Linux.
I got for more obscure versions and/or chop them about because I like to mess about with stuff. :)
So, in my minimal Void based Linux with just XFWM as a window manager but no actual desktop as such because I don't need icons all over my desktop making it messy or the kind of usual desktop menu options XFCE gives you, clicking on the desktop doesn't deactivate the active window! Clicking on another window does deactivate it.
I am using something called xclickroot to detect mouse clicks on the desktop and the only thing it checks for is a right click which then launches jgmenu which is my preferred dynamic applications menu. Launching jgmenu has the desired effect of stealing focus but is not the ideal solution, so I had to add something as a left click option to get it to unfocus/deactivate the window to work properly. I managed to get it working with Axolotls example and xdotool to fake clicking elsewhere.
Your code works on more standard versions of Linux window managers/environments, but even with my workaround it doesn't work in this Void based OS that I use mostly. I'm sure I could get around it if I needed to, but as I said, Axolotl's idea fixed it simply enough.
Interestingly, or not, in your code example, dragging the window via the title bar causes a "mouse clicked outside" message in the debugger. I don't know if it's supposed to do that? Also, I'm no wiser as to what threads are. :?

Thanks again for your help, I will probably have more obscure questions/requirements in the future. ;)

Moulder.
"If it ain't broke, fix it until it is!

This message is brought to you thanks to SenselessComments.com

My PB stuff for Linux: "https://u.pcloud.link/publink/show?code ... z3MR0T3jyV
RASHAD
PureBasic Expert
PureBasic Expert
Posts: 4991
Joined: Sun Apr 12, 2009 6:27 am

Re: Detecting left mouse click outside window

Post by RASHAD »

It doesn't matter which way you went through
It does matter that your problems are solved
Happy sailing with PB
Egypt my love
User avatar
moulder61
Enthusiast
Enthusiast
Posts: 205
Joined: Sun Sep 19, 2021 6:16 pm
Location: U.K.

Re: Detecting left mouse click outside window

Post by moulder61 »

RASHAD wrote: Thu Jul 18, 2024 10:07 am It doesn't matter which way you went through
It does matter that your problems are solved
Happy sailing with PB
Thanks again for your input.
My problems will never be solved. Trust me. ;)
There's a saying "If it ain't broke, don't fix it".
I say, "If it ain't broke, fix it until it is!". :lol:

Moulder.
"If it ain't broke, fix it until it is!

This message is brought to you thanks to SenselessComments.com

My PB stuff for Linux: "https://u.pcloud.link/publink/show?code ... z3MR0T3jyV
Post Reply