@@ -49,6 +49,11 @@ import (
4949 "gioui.org/app/internal/xkb"
5050)
5151
52+ const (
53+ _NET_WM_STATE_REMOVE = 0
54+ _NET_WM_STATE_ADD = 1
55+ )
56+
5257type x11Window struct {
5358 w * callbacks
5459 x * C.Display
@@ -81,6 +86,10 @@ type x11Window struct {
8186 wmStateFullscreen C.Atom
8287 // "_NET_ACTIVE_WINDOW"
8388 wmActiveWindow C.Atom
89+ // _NET_WM_STATE_MAXIMIZED_HORZ
90+ wmStateMaximizedHorz C.Atom
91+ // _NET_WM_STATE_MAXIMIZED_VERT
92+ wmStateMaximizedVert C.Atom
8493 }
8594 stage system.Stage
8695 metric unit.Metric
@@ -241,37 +250,16 @@ func (w *x11Window) SetWindowMode(mode WindowMode) {
241250 var action C.long
242251 switch mode {
243252 case Windowed :
244- action = 0 // _NET_WM_STATE_REMOVE
253+ action = _NET_WM_STATE_REMOVE
245254 case Fullscreen :
246- action = 1 // _NET_WM_STATE_ADD
255+ action = _NET_WM_STATE_ADD
247256 default :
248257 return
249258 }
250259 w .config .Mode = mode
251260 // "A Client wishing to change the state of a window MUST send
252261 // a _NET_WM_STATE client message to the root window."
253- var xev C.XEvent
254- ev := (* C .XClientMessageEvent )(unsafe .Pointer (& xev ))
255- * ev = C.XClientMessageEvent {
256- _type : C .ClientMessage ,
257- display : w .x ,
258- window : w .xw ,
259- message_type : w .atoms .wmState ,
260- format : 32 ,
261- }
262- arr := (* [5 ]C.long )(unsafe .Pointer (& ev .data ))
263- arr [0 ] = action
264- arr [1 ] = C .long (w .atoms .wmStateFullscreen )
265- arr [2 ] = 0
266- arr [3 ] = 1 // application
267- arr [4 ] = 0
268- C .XSendEvent (
269- w .x ,
270- C .XDefaultRootWindow (w .x ), // MUST be the root window
271- C .False ,
272- C .SubstructureNotifyMask | C .SubstructureRedirectMask ,
273- & xev ,
274- )
262+ w .sendWMStateEvent (action , w .atoms .wmStateFullscreen , 0 )
275263}
276264
277265func (w * x11Window ) ShowTextInput (show bool ) {}
@@ -295,11 +283,54 @@ func (w *x11Window) Close() {
295283 C .XSendEvent (w .x , w .xw , C .False , C .NoEventMask , & xev )
296284}
297285
298- // Maximize the window. Not implemented for x11.
299- func (w * x11Window ) Maximize () {}
286+ // Maximize the window.
287+ func (w * x11Window ) Maximize () {
288+ w .sendWMStateEvent (_NET_WM_STATE_ADD , w .atoms .wmStateMaximizedHorz , w .atoms .wmStateMaximizedVert )
289+ }
290+
291+ // Center the window.
292+ func (w * x11Window ) Center () {
293+ screen := C .XDefaultScreen (w .x )
294+ width := C .XDisplayWidth (w .x , screen )
295+ height := C .XDisplayHeight (w .x , screen )
296+
297+ var attrs C.XWindowAttributes
298+ C .XGetWindowAttributes (w .x , w .xw , & attrs )
299+ width -= attrs .border_width
300+ height -= attrs .border_width
300301
301- // Center the window. Not implemented for x11.
302- func (w * x11Window ) Center () {}
302+ sz := w .config .Size
303+ x := (int (width ) - sz .X ) / 2
304+ y := (int (height ) - sz .Y ) / 2
305+
306+ C .XMoveResizeWindow (w .x , w .xw , C .int (x ), C .int (y ), C .uint (sz .X ), C .uint (sz .Y ))
307+ }
308+
309+ // action is one of _NET_WM_STATE_REMOVE, _NET_WM_STATE_ADD.
310+ func (w * x11Window ) sendWMStateEvent (action C.long , atom1 , atom2 C.ulong ) {
311+ var xev C.XEvent
312+ ev := (* C .XClientMessageEvent )(unsafe .Pointer (& xev ))
313+ * ev = C.XClientMessageEvent {
314+ _type : C .ClientMessage ,
315+ display : w .x ,
316+ window : w .xw ,
317+ message_type : w .atoms .wmState ,
318+ format : 32 ,
319+ }
320+ data := (* [5 ]C.long )(unsafe .Pointer (& ev .data ))
321+ data [0 ] = C .long (action )
322+ data [1 ] = C .long (atom1 )
323+ data [2 ] = C .long (atom2 )
324+ data [3 ] = 1 // application
325+
326+ C .XSendEvent (
327+ w .x ,
328+ C .XDefaultRootWindow (w .x ), // MUST be the root window
329+ C .False ,
330+ C .SubstructureNotifyMask | C .SubstructureRedirectMask ,
331+ & xev ,
332+ )
333+ }
303334
304335var x11OneByte = make ([]byte , 1 )
305336
@@ -735,6 +766,8 @@ func newX11Window(gioWin *callbacks, options []Option) error {
735766 w .atoms .wmState = w .atom ("_NET_WM_STATE" , false )
736767 w .atoms .wmStateFullscreen = w .atom ("_NET_WM_STATE_FULLSCREEN" , false )
737768 w .atoms .wmActiveWindow = w .atom ("_NET_ACTIVE_WINDOW" , false )
769+ w .atoms .wmStateMaximizedHorz = w .atom ("_NET_WM_STATE_MAXIMIZED_HORZ" , false )
770+ w .atoms .wmStateMaximizedVert = w .atom ("_NET_WM_STATE_MAXIMIZED_VERT" , false )
738771
739772 // extensions
740773 C .XSetWMProtocols (dpy , win , & w .atoms .evDelWindow , 1 )
0 commit comments