diff options
author | graemeg <graemeg@ae50a9b5-8222-0410-bf8d-8a13f76226bf> | 2008-01-03 11:40:27 +0000 |
---|---|---|
committer | graemeg <graemeg@ae50a9b5-8222-0410-bf8d-8a13f76226bf> | 2008-01-03 11:40:27 +0000 |
commit | b742ef33b0d8657e556e1182bccd89c224bff844 (patch) | |
tree | c07d96d1c5cfdeed175f1b1f7a2bfae1ec6accdd /src | |
parent | 47eae709235dc3607d643ed0caff42d8489b6912 (diff) | |
download | fpGUI-b742ef33b0d8657e556e1182bccd89c224bff844.tar.xz |
* Reworked the timing of when windows get removed from the
internal lookup list.
* Reordered some methods on destruction of a form.
* fpGFX-X11 now reports lost windows for X11 events.
* Added extra checks in the X11 event handling to make sure we have found a actual window
before we try and process the event. This fixes the crashing of applications when you
close a window by clicking the X button on System Menu.
Diffstat (limited to 'src')
-rw-r--r-- | src/corelib/x11/gfx_x11.pas | 90 | ||||
-rw-r--r-- | src/gui/gui_form.pas | 2 |
2 files changed, 74 insertions, 18 deletions
diff --git a/src/corelib/x11/gfx_x11.pas b/src/corelib/x11/gfx_x11.pas index 5d3adfd4..a7b37812 100644 --- a/src/corelib/x11/gfx_x11.pas +++ b/src/corelib/x11/gfx_x11.pas @@ -130,6 +130,7 @@ type protected FWinFlags : TXWindowStateFlags; FWinHandle: TfpgWinHandle; + FBackupWinHandle: TfpgWinHandle; // Used by DestroyNotify & UnmapNotify events FModalForWin: TfpgWindowImpl; procedure DoAllocateWindowHandle(AParent: TfpgWindowBase); override; procedure DoReleaseWindowHandle; override; @@ -349,6 +350,29 @@ begin end; p := p^.Next; end; + {$IFDEF DEBUG} + writeln('GFX/X11: FindWindowByHandle failed to find <', IntToHex(wh, 9), '>'); + {$ENDIF} + Result := nil; +end; + +function FindWindowByBackupHandle(wh: TfpgWinHandle): TfpgWindowImpl; +var + p: PWindowLookupRec; +begin + p := FirstWindowLookupRec; + while p <> nil do + begin + if p^.w.FBackupWinHandle = wh then + begin + Result := p^.w; + Exit; + end; + p := p^.Next; + end; + {$IFDEF DEBUG} + writeln('GFX/X11: FindWindowByBackupHandle failed to find <', IntToHex(wh, 9), '>'); + {$ENDIF} Result := nil; end; @@ -669,6 +693,15 @@ var writeln('result of xlookupstring [' + s + ']'); writeln(Format('*** keysym [%s] ', [XKeysymToString(keysym)])); end; + + // Debug info only + procedure ReportLostWindow(const event: TXEvent); + begin + {$IFDEF DEBUG} + writeln('fpGFX/X11: ', GetXEventName(event._type), ' can''t find <', + IntToHex(event.xany.window, 9), '>'); + {$ENDIF} + end; begin xfd := XConnectionNumber(display); @@ -716,7 +749,11 @@ begin if kwg <> nil then w := kwg else + begin w := FindWindowByHandle(ev.xkey.window); + if not Assigned(w) then + ReportLostWindow(ev); + end; //Writeln('XKey event(',ev._type,'):', //IntToHex(ev.xkey.keycode,4),' (',ev.xkey.keycode,'), shift=',IntToHex(ev.xkey.state,4)); @@ -756,6 +793,9 @@ begin if (Popup <> nil) then begin w := FindWindowByHandle(ev.xbutton.window); + if not Assigned(w) then + ReportLostWindow(ev); + ew := w; while (w <> nil) and (w.Parent <> nil) do w := TfpgWindowImpl(w.Parent); // check the actual usage of Parent and where it gets set!! @@ -837,6 +877,8 @@ begin until not XCheckTypedWindowEvent(display, ev.xbutton.window, X.MotionNotify, @ev); w := FindWindowByHandle(ev.xany.window); + if not Assigned(w) then + ReportLostWindow(ev); if xapplication.TopModalForm <> nil then begin // This is ugly!!!!!!!!!!!!!!! @@ -858,12 +900,15 @@ begin // message blockings for modal windows X.ClientMessage: begin - w := FindWindowByHandle(ev.xany.window); + w := FindWindowByBackupHandle(ev.xany.window); + if not Assigned(w) then + ReportLostWindow(ev); + // WM_PROTOCOLS message - if ev.xclient.message_type = xia_wm_protocols then + if Assigned(w) and (ev.xclient.message_type = xia_wm_protocols) then begin //WriteLn(XGetAtomName(FDisplay, TAtom(ev.xclient.data.l[0]))); - if (ev.xclient.data.l[0] = netlayer.NetAtom[naWM_PING]) then + if (ev.xclient.data.l[0] = netlayer.NetAtom[naWM_PING]) then begin // always respond to pings or the wm will kill us netlayer.WindowReplyToPING(w.FWinHandle, @ev.xclient); @@ -896,7 +941,10 @@ begin msgp.rect.Width := ev.xconfigure.Width; msgp.rect.Height := ev.xconfigure.Height; - w := FindWindowByHandle(ev.xconfigure.window); + w := FindWindowByBackupHandle(ev.xconfigure.window); + if not Assigned(w) then + ReportLostWindow(ev); + if w <> nil then begin if w.FWindowType <> wtChild then @@ -945,23 +993,28 @@ begin X.MapNotify: begin w := FindWindowByHandle(ev.xmap.window); - if w <> nil then begin + if w <> nil then Include(w.FWinFlags, xwsfMapped); - end; end; + X.UnmapNotify: begin - w := FindWindowByHandle(ev.xunmap.window); - if w <> nil then begin + // special case which uses a different find window method + w := FindWindowByBackupHandle(ev.xunmap.window); + if not Assigned(w) then + ReportLostWindow(ev) + else Exclude(w.FWinFlags, xwsfMapped); - end; end; - { We handle this event manually as well. } X.DestroyNotify: begin - //Writeln('DestroyNotify'); - //fpgPostMessage(nil, FindWindowByHandle(ev.xany.window), FPGM_CLOSE); + // special case which uses a different find window method + w := FindWindowByBackupHandle(ev.xany.window); + if not Assigned(w) then + ReportLostWindow(ev) + else + RemoveWindowLookup(TfpgWindowImpl(w)); end; X.GraphicsExpose, @@ -976,10 +1029,10 @@ begin X.ReparentNotify: begin - // We are not interrested in this event + // We are not interrested in this event yet end; + else - {$Note This needs attention. We still have two events slipping by.} WriteLn('fpGFX/X11: Unhandled X11 event received: ', GetXEventName(ev._type)); end; end; @@ -1016,7 +1069,7 @@ var mask: longword; hints: TXSizeHints; begin - if FWinHandle > 0 then + if HandleIsValid then Exit; //==> if aparent <> nil then @@ -1042,6 +1095,7 @@ begin mask, @attr); FWinHandle := wh; + FBackupWinHandle := wh; // so newish window manager can close unresponsive programs if AParent = nil then // is a toplevel window @@ -1132,8 +1186,9 @@ begin if FWinHandle <= 0 then Exit; - RemoveWindowLookup(self); XDestroyWindow(xapplication.Display, FWinHandle); + // RemoveWindowLookup is now deferred to DestroyNotify event. +// RemoveWindowLookup(self); FWinHandle := 0; end; @@ -1161,7 +1216,7 @@ end; procedure TfpgWindowImpl.DoMoveWindow(const x: TfpgCoord; const y: TfpgCoord); begin - if FWinHandle > 0 then + if HandleIsValid then XMoveWindow(xapplication.display, FWinHandle, x, y); end; @@ -1251,6 +1306,7 @@ constructor TfpgWindowImpl.Create(AOwner: TComponent); begin inherited Create(AOwner); FWinHandle := 0; + FBackupWinHandle := 0; end; procedure TfpgWindowImpl.CaptureMouse; diff --git a/src/gui/gui_form.pas b/src/gui/gui_form.pas index 5b5ca64c..bf2ae6bc 100644 --- a/src/gui/gui_form.pas +++ b/src/gui/gui_form.pas @@ -318,8 +318,8 @@ end; procedure TfpgForm.Close; begin - fpgApplication.RemoveComponent(self); Hide; + fpgApplication.RemoveComponent(self); if fpgApplication.MainForm = self then fpgApplication.Terminated := True; end; |