Fix x/window.go
This commit is contained in:
		
							parent
							
								
									ee64650c19
								
							
						
					
					
						commit
						b58932f02b
					
				
							
								
								
									
										121
									
								
								x/window.go
									
									
									
									
									
								
							
							
						
						
									
										121
									
								
								x/window.go
									
									
									
									
									
								
							| @ -1,6 +1,7 @@ | |||||||
| package x | package x | ||||||
| 
 | 
 | ||||||
| import "image" | import "image" | ||||||
|  | import "strings" | ||||||
| 
 | 
 | ||||||
| import "git.tebibyte.media/tomo/tomo" | import "git.tebibyte.media/tomo/tomo" | ||||||
| import "git.tebibyte.media/tomo/tomo/data" | import "git.tebibyte.media/tomo/tomo/data" | ||||||
| @ -41,7 +42,10 @@ type window struct { | |||||||
| 		innerBounds image.Rectangle // bounds of the drawable area | 		innerBounds image.Rectangle // bounds of the drawable area | ||||||
| 	} | 	} | ||||||
| 
 | 
 | ||||||
| 	onClose event.FuncBroadcaster | 	on struct { | ||||||
|  | 		close    event.FuncBroadcaster | ||||||
|  | 		tryClose event.Broadcaster[func () bool] | ||||||
|  | 	} | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| type windowLink struct { | type windowLink struct { | ||||||
| @ -64,27 +68,12 @@ func (this *windowLink) NotifyMinimumSizeChange () { | |||||||
| 	this.window.doMinimumSize() | 	this.window.doMinimumSize() | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| func (this *Backend) NewWindow ( | func (this *Backend) NewWindow (kind tomo.WindowKind, bounds image.Rectangle) (tomo.Window, error) { | ||||||
| 	bounds image.Rectangle, |  | ||||||
| ) ( |  | ||||||
| 	output tomo.Window, |  | ||||||
| 	err error, |  | ||||||
| ) { |  | ||||||
| 	this.assert() |  | ||||||
| 	return this.newWindow(bounds, false) |  | ||||||
| } |  | ||||||
| 
 |  | ||||||
| func (this *Backend) NewPlainWindow ( |  | ||||||
| 	bounds image.Rectangle, |  | ||||||
| ) ( |  | ||||||
| 	output tomo.Window, |  | ||||||
| 	err error, |  | ||||||
| ) { |  | ||||||
| 	this.assert() | 	this.assert() | ||||||
| 	window, err := this.newWindow(bounds, false) | 	window, err := this.newWindow(bounds, false) | ||||||
| 	window.setType("dock") | 	if err != nil { return nil, err } | ||||||
| 	 | 	window.setKind(kind) | ||||||
| 	return window, err | 	return window, nil | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| func (this *Backend) newWindow ( | func (this *Backend) newWindow ( | ||||||
| @ -131,7 +120,11 @@ func (this *Backend) newWindow ( | |||||||
| 	if err != nil { return } | 	if err != nil { return } | ||||||
| 
 | 
 | ||||||
| 	window.xWindow.WMGracefulClose (func (xWindow *xwindow.Window) { | 	window.xWindow.WMGracefulClose (func (xWindow *xwindow.Window) { | ||||||
| 		window.Close() | 		holdOff := false | ||||||
|  | 		for _, callback := range window.on.tryClose.Listeners() { | ||||||
|  | 			if !callback() { holdOff = true } | ||||||
|  | 		} | ||||||
|  | 		if !holdOff { window.Close() } | ||||||
| 	}) | 	}) | ||||||
| 
 | 
 | ||||||
| 	xevent.ExposeFun(window.handleExpose). | 	xevent.ExposeFun(window.handleExpose). | ||||||
| @ -247,56 +240,29 @@ func (this *window) SetBounds (bounds image.Rectangle) { | |||||||
| 		bounds.Min.Y + bounds.Dy()) | 		bounds.Min.Y + bounds.Dy()) | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| func (this *window) NewChild (bounds image.Rectangle) (tomo.Window, error) { | func (this *window) NewChild (kind tomo.WindowKind, bounds image.Rectangle) (tomo.Window, error) { | ||||||
| 	leader := this.leader | 	leader := this.leader | ||||||
| 	 | 	 | ||||||
| 	child, err := this.backend.newWindow ( | 	child, err := this.backend.newWindow ( | ||||||
| 		bounds.Add(this.metrics.innerBounds.Min), false) | 		bounds.Add(this.metrics.innerBounds.Min), false) | ||||||
| 	child.leader = leader |  | ||||||
| 	if err != nil { return nil, err } | 	if err != nil { return nil, err } | ||||||
| 	 | 	 | ||||||
| 	child.setClientLeader(leader) | 	child.leader = leader | ||||||
| 	leader.setClientLeader(leader) | 	err = child.setKind(kind) | ||||||
|  | 	if err != nil { return nil, err } | ||||||
|  | 	if kind == tomo.WindowKindModal { | ||||||
|  | 		this.hasModal     = true | ||||||
|  | 		child.modalParent = this | ||||||
|  | 	} | ||||||
| 	 | 	 | ||||||
| 	icccm.WmTransientForSet ( | 	icccm.WmTransientForSet ( | ||||||
| 		this.backend.x, | 		this.backend.x, | ||||||
| 		child.xWindow.Id, | 		child.xWindow.Id, | ||||||
| 		leader.xWindow.Id) | 		leader.xWindow.Id) | ||||||
| 	child.setType("UTILITY") |  | ||||||
| 	// child.inheritProperties(leader.window) | 	// child.inheritProperties(leader.window) | ||||||
| 	return child, err | 	return child, err | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| func (this *window) NewMenu (bounds image.Rectangle) (tomo.Window, error) { |  | ||||||
| 	menu, err := this.backend.newWindow ( |  | ||||||
| 		bounds.Add(this.metrics.innerBounds.Min), true) |  | ||||||
| 	menu.shy = true |  | ||||||
| 	icccm.WmTransientForSet ( |  | ||||||
| 		this.backend.x, |  | ||||||
| 		menu.xWindow.Id, |  | ||||||
| 		this.xWindow.Id) |  | ||||||
| 	menu.setType("POPUP_MENU") |  | ||||||
| 	// menu.inheritProperties(this) |  | ||||||
| 	return menu, err |  | ||||||
| } |  | ||||||
| 
 |  | ||||||
| func (this *window) NewModal (bounds image.Rectangle) (tomo.Window, error) { |  | ||||||
| 	modal, err := this.backend.newWindow ( |  | ||||||
| 		bounds.Add(this.metrics.innerBounds.Min), false) |  | ||||||
| 	icccm.WmTransientForSet ( |  | ||||||
| 		this.backend.x, |  | ||||||
| 		modal.xWindow.Id, |  | ||||||
| 		this.xWindow.Id) |  | ||||||
| 	ewmh.WmStateSet ( |  | ||||||
| 		this.backend.x, |  | ||||||
| 		modal.xWindow.Id, |  | ||||||
| 		[]string { "_NET_WM_STATE_MODAL" }) |  | ||||||
| 	modal.modalParent = this |  | ||||||
| 	this.hasModal     = true |  | ||||||
| 	// modal.inheritProperties(window) |  | ||||||
| 	return modal, err |  | ||||||
| } |  | ||||||
| 
 |  | ||||||
| func (this *window) Modifiers () input.Modifiers { | func (this *window) Modifiers () input.Modifiers { | ||||||
| 	return this.hierarchy.Modifiers() | 	return this.hierarchy.Modifiers() | ||||||
| } | } | ||||||
| @ -330,12 +296,12 @@ func (this *window) Visible () bool { | |||||||
| 	return this.visible | 	return this.visible | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| func (this *window) Close () { | func (this *window) Close () error { | ||||||
| 	xevent   .Detach(this.backend.x, this.xWindow.Id) | 	xevent   .Detach(this.backend.x, this.xWindow.Id) | ||||||
| 	keybind  .Detach(this.backend.x, this.xWindow.Id) | 	keybind  .Detach(this.backend.x, this.xWindow.Id) | ||||||
| 	mousebind.Detach(this.backend.x, this.xWindow.Id) | 	mousebind.Detach(this.backend.x, this.xWindow.Id) | ||||||
| 
 | 
 | ||||||
| 	this.onClose.Broadcast() | 	this.on.close.Broadcast() | ||||||
| 	if this.modalParent != nil { | 	if this.modalParent != nil { | ||||||
| 		// we are a modal dialog, so unlock the parent | 		// we are a modal dialog, so unlock the parent | ||||||
| 		this.modalParent.hasModal = false | 		this.modalParent.hasModal = false | ||||||
| @ -345,10 +311,15 @@ func (this *window) Close () { | |||||||
| 	delete(this.backend.windows, this.xWindow.Id) | 	delete(this.backend.windows, this.xWindow.Id) | ||||||
| 	this.xWindow.Destroy() | 	this.xWindow.Destroy() | ||||||
| 	this.hierarchy.Close() | 	this.hierarchy.Close() | ||||||
|  | 	return nil // TODO maybe return an error? maybe join them? | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| func (this *window) OnClose (callback func ()) event.Cookie { | func (this *window) OnClose (callback func ()) event.Cookie { | ||||||
| 	return this.onClose.Connect(callback) | 	return this.on.close.Connect(callback) | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | func (this *window) OnTryClose (callback func () bool) event.Cookie { | ||||||
|  | 	return this.on.tryClose.Connect(callback) | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| func (this *window) grabInput () { | func (this *window) grabInput () { | ||||||
| @ -364,6 +335,19 @@ func (this *window) ungrabInput () { | |||||||
| 	mousebind.UngrabPointer(this.backend.x) | 	mousebind.UngrabPointer(this.backend.x) | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
|  | func (this *window) setKind (kind tomo.WindowKind) error { | ||||||
|  | 	err := this.setType(windowKindToType(kind)) | ||||||
|  | 	if err != nil { return err } | ||||||
|  | 	if kind == tomo.WindowKindModal { | ||||||
|  | 		err = this.setState("MODAL") | ||||||
|  | 		if err != nil { return err } | ||||||
|  | 	} | ||||||
|  | 	if kind == tomo.WindowKindMenu { | ||||||
|  | 		this.shy = true | ||||||
|  | 	} | ||||||
|  | 	return nil | ||||||
|  | } | ||||||
|  | 
 | ||||||
| func (this *window) setType (ty string) error { | func (this *window) setType (ty string) error { | ||||||
| 	return ewmh.WmWindowTypeSet ( | 	return ewmh.WmWindowTypeSet ( | ||||||
| 		this.backend.x, | 		this.backend.x, | ||||||
| @ -371,6 +355,13 @@ func (this *window) setType (ty string) error { | |||||||
| 		[]string { "_NET_WM_WINDOW_TYPE_" + ty }) | 		[]string { "_NET_WM_WINDOW_TYPE_" + ty }) | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
|  | func (this *window) setState (state string) error {	 | ||||||
|  | 	return ewmh.WmStateSet ( | ||||||
|  | 		this.backend.x, | ||||||
|  | 		this.xWindow.Id, | ||||||
|  | 		[]string { "_NET_WM_STATE_" + state }) | ||||||
|  | } | ||||||
|  | 
 | ||||||
| func (this *window) setClientLeader (leader *window) error { | func (this *window) setClientLeader (leader *window) error { | ||||||
| 	hints, _ := icccm.WmHintsGet(this.backend.x, this.xWindow.Id) | 	hints, _ := icccm.WmHintsGet(this.backend.x, this.xWindow.Id) | ||||||
| 	if hints == nil { | 	if hints == nil { | ||||||
| @ -476,3 +467,15 @@ func (this *window) doMinimumSize () { | |||||||
| 		this.xWindow.Resize(newWidth, newHeight) | 		this.xWindow.Resize(newWidth, newHeight) | ||||||
| 	} | 	} | ||||||
| } | } | ||||||
|  | 
 | ||||||
|  | func windowKindToType (kind tomo.WindowKind) string { | ||||||
|  | 	switch kind { | ||||||
|  | 	case tomo.WindowKindNormal:  return "NORMAL" | ||||||
|  | 	case tomo.WindowKindPlain:   return "DOCK" | ||||||
|  | 	case tomo.WindowKindUtility: return "UTILITY" | ||||||
|  | 	case tomo.WindowKindToolbar: return "TOOLBAR" | ||||||
|  | 	case tomo.WindowKindMenu:    return "POPUP_MENU" | ||||||
|  | 	case tomo.WindowKindModal:   return "NORMAL" | ||||||
|  | 	default:                     return strings.ReplaceAll(strings.ToUpper(string(kind)), " ", "_") | ||||||
|  | 	} | ||||||
|  | } | ||||||
|  | |||||||
		Loading…
	
	
			
			x
			
			
		
	
		Reference in New Issue
	
	Block a user